调试不 return 的异步任务

Debugging async tasks that don't return

我正在开发一个小型 WPF 桌面实用程序,并使用 async/await 方法来允许并行处理。

但是,我一直 运行 解决等待异步任务根本不会 returns 的问题。没有异常被抛出,如果我在调试器中暂停应用程序,调用堆栈说它是 运行 "External code" 由调用异步任务的行调用。 (具体来说,它挂在: WindowsBase.dll!System.Windows.Threading.DispatcherSynchronizationContext.Wait(System.IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) 在我当前的例子中。) 我已经多次看到这个问题并解决了它,但每次我都必须添加调试代码来找出停止执行的行。 (相同的代码可能在多次迭代后执行良好,然后挂起)同样的问题发生在等待我自己的异步方法和等待框架异步方法 E.G. Stream.CopyToAsync 和 Stream.ReadAsync)

有没有办法查看 Visual Studio 2017 年执行的任务?我尝试打开 "Tasks" window,但除了 "No tasks to display" 什么也没得到——可能我没有正确使用 window?

FWIW,我正在执行很多(数百个)并发后台操作,但 none 重叠。主要是 Web 服务调用、文件系统读取和 MD5 校验和计算。 async/await 在不冻结的情况下可以同时执行的操作是否受限?或者等待的最大嵌套数?

这看起来像是由于同步上下文导致的典型死锁案例。当您同步等待内部调用 await 的方法返回的任务时,就会发生这种情况。例如:

public void Deadlock()
{
    DoSomething.Wait();
}

public Task DoSomething()
{
    // Some stuff
    await DoSomethingElse();
    // More stuff
}

在同步上下文中时,await 的延续将发布到同一个同步上下文。但是同步上下文的线程正在等待 DoSomething().Wait(),因此不可用。我们陷入僵局:

  • continuation 正在等待同步上下文的线程可用
  • 同步上下文的线程正在等待任务完成,执行continuation时会出现这种情况

有两种可能的修复方法:

  • 停止同步等待任务
  • 等待时使用 .ConfigureAwait(false),这样延续就不会发布到同步上下文