调试不 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)
,这样延续就不会发布到同步上下文
我正在开发一个小型 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)
,这样延续就不会发布到同步上下文