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)...并且方法返回的任务将只完成当异步方法真的到了最后.
asyncawait是唯一允许使用关键字的语法糖。
如果async, await在ASP.NET Core中使用,那么你的请求线程将被释放到线程池中。
\n\n\n异步请求处理程序的操作方式不同。当请求传入时,ASP.NET 会获取其线程池线程之一并将其分配给该请求。这次请求处理程序将异步调用该外部资源。这会将请求线程返回到线程池,直到对外部资源的调用返回。图 3 显示了在请求同步等待外部资源时具有两个线程的线程池。
\n
\n\n重要的区别在于,当异步调用正在进行时,请求线程已返回到线程池。当线程位于线程池中时,它\xe2\x80\x99 不再与该请求相关联。这次,当外部资源调用返回时,ASP.NET\n将获取其线程池线程之一并将其重新分配给该请求。\n该线程继续处理该请求。当请求完成时,该线程将再次返回到线程池。请注意,对于同步处理程序,同一线程用于请求的生命周期;相反,对于异步处理程序,可以将不同的线程分配给同一请求(在不同的时间)。
\n
对于桌面应用程序:
\n\n\n\n\n
await释放当前线程,但不释放到线程池。\nUI 线程不是来自线程池。如果您运行异步方法,\ne.gExecuteScalarAsync如果没有async, await关键字,则该方法\n无论如何都将异步运行。调用线程不会受到影响。
例如,您有一个繁重的存储过程,并且您的存储过程需要 10 分钟才能执行。如果您在没有async, await关键字的情况下从 C# 运行此代码,那么您的执行线程将等待您的存储过程 10 分钟。这个等待线程不会执行任何操作,它只会等待存储过程。
但是,如果async, await使用关键字,那么您的线程将不会等待存储过程。该线程将有资格工作。
尽管乔恩·斯基特(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确定线程池中的哪个线程应该处理该信号。延续/回调(存储在状态机中)。
此外,以下文章也可能有用: