什么线程在 `await` 关键字之后运行代码? [英] What thread runs the code after the `await` keyword?
问题描述
让我举一个简单的例子:
Let me just post a simple example:
private void MyMethod()
{
Task task = MyAsyncMethod();
task.Wait();
}
private async Task MyAsyncMethod()
{
//Code before await
await MyOtherAsyncMethod();
//Code after await
}
假设我在单线程应用程序(如控制台应用程序)中运行上述代码.我很难理解代码 //Code after await
将如何运行.
我知道当我在 MyAsyncMethod()
中点击 await
关键字时,控件会返回到 MyMethod()
,但随后我锁定了线程使用 task.Wait()
.如果线程被锁定,如果应该使用它的线程被锁定,//Code after await
如何运行?
是否创建了一个新线程来运行 //Code after await
?还是主线程神奇地跳出task.Wait()
运行//Code after await
?
我不确定这应该如何工作?
Let's say I run the above code in a single threaded app -like a console app-. I'm having a difficult time understanding how the code //Code after await
would be able to run.
I understand that when I hit the await
keyword in MyAsyncMethod()
control goes back to MyMethod()
, but then I'm locking the thread with task.Wait()
. If the thread is locked, how can //Code after await
ever run if the thread that is supposed to take it is locked?
Does a new thread get created to run //Code after await
? Or does the main thread magically steps out of task.Wait()
to run //Code after await
?
I'm not sure how this is supposed to work?
推荐答案
如果从主线程调用,发布的代码将在 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 是 ThreadpoolTaskScheduler),所以 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.
这篇关于什么线程在 `await` 关键字之后运行代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!