在堆栈跟踪中,MessageProcessor.Dispose()
,OnThreadShutdownRequested
和RenewTaskLeaseCallback
都需要锁定以防止这些对象中的竞争条件。
线程的堆栈跟踪(ID14968)保存所有锁,这会导致其他线程阻塞并等待它释放锁。
问题在于,当在线程14968上调用CloseConnection()
时,连接永远不会关闭,SyncAsyncLock.Wait()
在CloseConnection()
内部被调用。呼叫被阻止,不会继续,并发生死锁情况。
调用CloseConnection()
时可能导致线程阻塞的内容是什么?
更大的图片here。
答案 0 :(得分:0)
在这个问题上工作了两天之后,我终于找到了问题所在。 有一种情况可能会导致应用程序陷入僵局。
TaskLeaseRenewer
对象实现IDisposable
,可以由多个线程访问。在类中使用锁以确保没有两个线程将尝试同时处置该对象。 TaskLeaseRenewer
有一个计时器和一个回调函数Callback
,它将由一个单独的线程定时调用。 Callback
主题会尝试在创建Thread.Abort()
的主题上调用TaskLeaseRenewer
,并最终在Dispose()
上调用TaskLeaseRenwer
当我尝试中止执行以下操作的线程时,会出现问题:
using(TaskLeaseRenewer renewer = new TaskLeaseRewnewer())
{
DoStuff();
}
我发现当你在一个带有Thread.Abort()
语句的线程上调用using
时,它不会终止该线程,直到它调用所使用对象的Dispose()
函数为止。
以下示例将在线程中止之前触发ConnectionWrapper.Dispose()
。
static void DisposeOnAbort()
{
Thread t = new Thread(() =>
{
Console.WriteLine("Using connection wrapper");
using (ConnectionWrapper wrapper = new ConnectionWrapper())
{
while (true)
{
Thread.Sleep(1000);
}
}
});
t.Start();
Thread.Sleep(1000);
Console.WriteLine("Aborting thread..");
t.Abort();
}
鉴于这些,我发现问题是当Callback()
调用Thread.Abort()
时,TaskLeaseRenewer.Dispose()
将在创建的线程上调用,因为线程已准备好被杀死。但是Callback()
函数位于不同的线程上,并且还持有Dispose()
函数试图获取的锁。 <{1}}将无法获取锁定,线程将永远不会终止。
解决此问题后,Dispose()
死锁似乎消失了。我仍然对阻止连接关闭的原因感兴趣。
在更多地解决这个问题之后,我发现当一个线程被中止时,总是会调用一次性对象的connection.Close()
对象。是否使用Dispose()
语句。 Callstack如下:
using