我总共有三个线程。第一个是主UI线程,该线程启动System.Threading.Thread
(ExperimentThread
),后者又启动BackgroundWorker
(WorkerThread
)。Thread.Join()导致死锁
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);
}
}
}
而对于完整性这里是WorkerThread
的DoWork的方法:
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线程将通过设置它的布尔字段设置为true的一个终止ExperimentThread
,然后等待它结束,如下所示:一旦
if (ExperimentThread.IsAlive)
{
ExperimentThread.StopThread = true;
ExperimentThread.Join(); // this line seems to cause the deadlock?
}
为加入()被调用时,正在访问的共享资源上出现死锁ExperimentThread
和WorkerThread
,并且我的应用程序无限期地挂起。这可能发生在10次中的9次。
如果从我上面的代码段删除ExperimentThread.Join()
,僵局永远不会发生,并ExperimentThread
似乎正常终止(它然后继续通过调用CancelAsync()
终止WorkerThread
)。
任何想法可能是这里的问题? (PS我一直在使用Console.WriteLine()来确定什么时候获取和释放锁,这是什么导致我相信有一个死锁。有没有更好的来确定这一点,我可能是错的? )
你可以包含你的'ExperimentThread'执行的代码吗? –
没有足够的代码显示此处以确定真正原因... –
'Thread.Join()导致死锁' - yup,这只是Join()的正常行为,或任何其他类型的硬等待,在GUI应用程序事件处理程序。我已经看到几十年来以各种语言使用各种语言死锁的图形用户界面,但我们仍然得到'你必须等待线程从加入/等待/任何'结束从愚蠢的线程介绍网站。 35年来为缺乏经验的多线程开发人员喂养了同样的垃圾。 –