在'async'方法上达到'await'时线程会发生什么?

Guy*_*gal 11 c# multithreading asynchronous ctp async-await

我的标题提出的问题是关于'异步'和'等待'的背景.

说当前线程到达'await'关键字是什么,它会进入"休眠",并在await方法完成时唤醒,这是真的吗?

谢谢!

家伙

Jon*_*eet 23

说当前线程到达'await'关键字是什么,它会进入"休眠",并在await方法完成时唤醒,这是真的吗?

不是.重点async避免线程在做其他工作时睡觉.另外,如果运行async方法的线程是一个UI线程,那么你真的不希望它在休眠 - 你希望它可用于其他事件.

当执行到达await表达式时,生成的代码将检查您正在等待的事物是否已经可用.如果是,你可以使用它并继续前进.否则,它将为"等待"部分添加一个延续,并立即返回.

继续确保在等待值准备好时运行异步方法的其余部分.发生在哪个线程取决于您正在等待的上下文 - 如果异步方法在线程池线程中运行,则延续可以在与该方法启动的线程不同的线程上运行...但是不应该物.(其余的上下文仍将传播.)

请注意,async方法在没有完成的情况下返回是很好的 - 因为异步方法不能直接返回值 - 它总是返回一个Task<T>(或Task,或void)...并且方法返回的任务将只完成当异步方法真的到了最后.


Ste*_*pUp 8

asyncawait是唯一允许使用关键字的语法糖。

\n

如果async, await在ASP.NET Core中使用,那么你的请求线程将被释放到线程池中。

\n

正如斯蒂芬·克利里所说:

\n
\n

异步请求处理程序的操作方式不同。当请求传入时,ASP.NET 会获取其线程池线程之一并将其分配给该请求。这次请求处理程序将异步调用该外部资源。这会将请求线程返回到线程池,直到对外部资源的调用返回。图 3 显示了在请求同步等待外部资源时具有两个线程的线程池。

\n
\n

在此输入图像描述

\n
\n

重要的区别在于,当异步调用正在进行时,请求线程已返回到线程池。当线程位于线程池中时,它\xe2\x80\x99 不再与该请求相关联。这次,当外部资源调用返回时,ASP.NET\n将获取其线程池线程之一并将其重新分配给该请求。\n该线程继续处理该请求。当请求完成时,该线程将再次返回到线程池。请注意,对于同步处理程序,同一线程用于请求的生命周期;相反,对于异步处理程序,可以将不同的线程分配给同一请求(在不同的时间)。

\n
\n

对于桌面应用程序:

\n
\n

await释放当前线程,但不释放到线程池。\nUI 线程不是来自线程池。如果您运行异步方法,\ne.g ExecuteScalarAsync如果没有async, await关键字,则该方法\n无论如何都将异步运行。调用线程不会受到影响。

\n

特别感谢Panagiotis Kanavos的好评。

\n
\n

例如,您有一个繁重的存储过程,并且您的存储过程需要 10 分钟才能执行。如果您在没有async, await关键字的情况下从 C# 运行此代码,那么您的执行线程将等待您的存储过程 10 分钟。这个等待线程不会执行任何操作,它只会等待存储过程。

\n

但是,如果async, await使用关键字,那么您的线程将不会等待存储过程。该线程将有资格工作。

\n


Mil*_*idi 6

尽管乔恩·斯基特(Jon Skeet)已经回答了这个问题,他是一位技术精湛的人(也是我最喜欢的人之一),但对于本文的其他读者来说,我在下面提到的内容还是值得阅读的。

通过async在方法上使用关键字,原始异步方法创建一个状态机实例,使用捕获的状态(this如果该方法不是静态的,则包括指针)对其进行初始化,然后通过使用AsyncTaskMethodBuilder<T>.Start通过引用传递的状态机实例进行调用来开始执行。

一旦控制到达await关键字,当前线程(可以是 .Net 线程池的工作线程)就会创建一个回调(作为 a ),以使用SynchronizationContext/在关键字(Continuationdelegate )之后执行同步代码的其余部分TaskSheduler的 API(可能并不存在于所有应用程序中,例如控制台应用程序或 ASP.Net Core Web 应用程序),捕获的内容作为对象存储在状态机中,IO 工作发送到IOCP 线程,并且然后释放当前线程。awaitSynchronizationContextSynchronizationContext

IOCP线程绑定一个IOCP(IO Completion Port),打开一个连接,要求其执行已经等待的代码,IOCP将执行命令发送到相应的设备(socket/drive)。

每当相关设备完成 IO 工作时,来自 IOCP 的信号连同 IO 工作的结果一起返回到 IOCP 线程,然后 IOCP 线程根据捕获的信号SynchronizationContext确定线程池中的哪个线程应该处理该信号。延续/回调(存储在状态机中)。

在此输入图像描述

此外,以下文章也可能有用:

  1. https://devblogs.microsoft.com/premier-developer/dissecting-the-async-methods-in-c/
  2. https://tooslowexception.com/net-asyncawait-in-a-single-picture/
  3. https://devblogs.microsoft.com/dotnet/configureawait-faq/#what-is-a-synchronizationcontext