1

全部で 3 つのスレッドがあります。1 つ目はメイン UI スレッドで、System.Threading.Thread( ExperimentThread) を開始し、次にBackgroundWorker( WorkerThread) を開始します。

MainThreadWorkerThreadどちらも共有リソースにアクセスします。このリソースへのアクセスを次のオブジェクトと同期します。

private static readonly Object LockObject = new Object();

各スレッドのメインループで次のように使用します。

lock (LockObject)
{
    // Do something with shared resource here.
}

のカットダウン バージョンExperimentThreadは次のとおりです。

public void RunExperiment
{
    while (!bStopThread)
    {

        lock (LockObject)
        {
            // Do something with shared resource here.
        }

        if (bStopThread)
        {
            break;
        }
        else
        {
            Application.DoEvents();
            Thread.Sleep(250);
        }
    }
}

完全を期すために、次の DoWork メソッドを示しWorkerThreadます。

private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker Worker = sender as BackgroundWorker;

    for (int X = 0; X < 200; X++)
    {
        if (Worker.CancellationPending)
        {
            e.Cancel = true;
            return;
        }

        lock (LockObject)
        {
            // Do something with shared resource here.
        }
    }
}

両方のスレッドが自由に実行されている場合、これはうまくいくようです。

ある時点で、UI スレッドはExperimentThread、ブール フィールドの 1 つを true に設定して を終了し、次のように終了するまで待機します。

if (ExperimentThread.IsAlive)
{
    ExperimentThread.StopThread = true;
    ExperimentThread.Join();    // this line seems to cause the deadlock?
}

ExperimentThreadJoin() が呼び出されるとすぐに、とによってアクセスされている共有リソースでデッドロックが発生しWorkerThread、アプリケーションが無期限にハングします。これはおそらく10回中9回発生します。

ExperimentThread.Join()上記のコード スニペットから削除すると、デッドロックは発生せず、正常に終了したように見えます (その後、 を呼び出しExperimentThreadて終了します)。WorkerThreadCancelAsync()

ここで何が問題になる可能性がありますか?

(PS 私は Console.WriteLine() を使用して、ロックがいつ取得され、いつ解放されるかを判断してきました。これが、デッドロックがあると私に信じさせたものです。これを判断するより良い方法はありますか?)

4

1 に答える 1