我一共有三个线程。第一个是主 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
通过将其布尔字段之一设置为 true 来终止,然后等待它结束,如下所示:
if (ExperimentThread.IsAlive)
{
ExperimentThread.StopThread = true;
ExperimentThread.Join(); // this line seems to cause the deadlock?
}
一旦调用 Join(),就会在被访问的共享资源上发生死锁,ExperimentThread
并且WorkerThread
访问的共享资源就会发生死锁,并且我的应用程序将无限期挂起。这可能会发生 10 次中的 9 次。
如果我ExperimentThread.Join()
从上面的代码片段中删除,死锁永远不会发生,并且ExperimentThread
似乎可以正常终止(然后它WorkerThread
通过调用继续终止CancelAsync()
来终止)。
有什么想法可能是这里的问题吗?
(PS 我一直在使用 Console.WriteLine() 来确定何时获取和释放锁,这使我相信存在死锁。有没有更好的方法来确定这一点,我可能是错的?)