全部で 3 つのスレッドがあります。1 つ目はメイン UI スレッドで、System.Threading.Thread
( ExperimentThread
) を開始し、次にBackgroundWorker
( WorkerThread
) を開始します。
MainThread
WorkerThread
どちらも共有リソースにアクセスします。このリソースへのアクセスを次のオブジェクトと同期します。
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?
}
ExperimentThread
Join() が呼び出されるとすぐに、とによってアクセスされている共有リソースでデッドロックが発生しWorkerThread
、アプリケーションが無期限にハングします。これはおそらく10回中9回発生します。
ExperimentThread.Join()
上記のコード スニペットから削除すると、デッドロックは発生せず、正常に終了したように見えます (その後、 を呼び出しExperimentThread
て終了します)。WorkerThread
CancelAsync()
ここで何が問題になる可能性がありますか?
(PS 私は Console.WriteLine() を使用して、ロックがいつ取得され、いつ解放されるかを判断してきました。これが、デッドロックがあると私に信じさせたものです。これを判断するより良い方法はありますか?)