这是我发现在某些情况下很难调试等待任务中的死锁的一个简化示例:
class Program
{
static void Main(string[] args)
{
var task = Hang();
task.Wait();
}
static async Task Hang()
{
var tcs = new TaskCompletionSource<object>();
// do some more stuff. e.g. another await Task.FromResult(0);
await tcs.Task;
tcs.SetResult(0);
}
}
Run Code Online (Sandbox Code Playgroud)
这个例子很容易理解为什么它会死锁,它正在等待稍后完成的任务。这看起来很愚蠢,但在更复杂的生产代码中可能会发生类似的情况,并且由于缺乏多线程经验可能会错误地引入死锁。
这个例子的有趣之处在于Hang方法内部没有像Task.Wait()or那样的线程阻塞代码Task.Result。然后当我附加 VS 调试器时,它只显示主线程正在等待任务完成。但是,没有线程显示代码在Hang使用并行堆栈视图的方法内部停止的位置。
这是我在并行堆栈中的每个线程上的调用堆栈(总共 3 个):
头1:
[Managed to Native Transition]
Microsoft.VisualStudio.HostingProcess.HostProc.WaitForThreadExit
Microsoft.VisualStudio.HostingProcess.HostProc.RunParkingWindowThread
System.Threading.ThreadHelper.ThreadStart_Context
System.Threading.ExecutionContext.RunInternal
System.Threading.ExecutionContext.Run
System.Threading.ExecutionContext.Run
System.Threading.ThreadHelper.ThreadStart
Run Code Online (Sandbox Code Playgroud)
主题 2:
[Managed to Native Transition]
Microsoft.Win32.SystemEvents.WindowThreadProc
System.Threading.ThreadHelper.ThreadStart_Context
System.Threading.ExecutionContext.RunInternal
System.Threading.ExecutionContext.Run
System.Threading.ExecutionContext.Run
System.Threading.ThreadHelper.ThreadStart …Run Code Online (Sandbox Code Playgroud)