且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

什么线程在 `await` 关键字之后运行代码?

更新时间:2023-01-13 07:39:17

如果从主线程调用,发布的代码将在 Winform App 中死锁",因为您使用 Wait() 阻塞了主线程代码>.

Code as posted will "Deadlock" in Winform App if called from main thread because you're blocking the main thread with the Wait().

但在控制台应用程序中这是有效的.但如何?

But in console app this works. but how?

答案隐藏在 SynchronizationContext.Current 中.await 捕获SynchronizationContext",当任务完成时,它将在同一个SynchronizationContext"中继续.

Answer is hidden in the SynchronizationContext.Current. await captures the "SynchronizationContext" and when the task is completed it will continue in the same "SynchronizationContext".

在 winform 应用程序中,SynchronizationContext.Current 将设置为 WindowsFormsSynchronizationContext,它将发布到对消息循环"的调用,但谁将处理它?主线程在 Wait() 中等待.

In winform app SynchronizationContext.Current will be set to WindowsFormsSynchronizationContext which will post to the call to "Message loop", but who is going to process that? out main thread is waiting in Wait().

在控制台应用程序中,SynchronizationContext.Current 不会默认设置,因此当没有SynchronizationContext"可用于等待捕获时,它将为 null 以便安排延续到 ThreadPool(TaskScheduler.Default 是 ThreadpoolTask​​Scheduler),所以 await 之后的代码(通过线程池线程)工作.

In console app SynchronizationContext.Current will not be set by default so it will be null when no "SynchronizationContext" available for await to capture so it will schedule the continuation to ThreadPool(TaskScheduler.Default which is ThreadpoolTaskScheduler) and so the code after await works(through threadpool thread).

可以使用 Task.ConfigureAwait(false); 控制上述捕获行为,这将防止 winform 应用程序死锁,但 await 之后的代码不再在 UI 线程中运行.

Aforementioned capturing behavior can be controlled using Task.ConfigureAwait(false); which will prevent winform app from deadlocking but code after await no longer runs in UI thread.