等待完全阻塞线程
本文关键字:线程 等待 | 更新日期: 2023-09-27 18:29:37
当我们在代码中使用await
时,通常awaiter会捕获上下文,并在等待的任务成功完成时将其用作回调。但是,由于await
通常是No Op(No Operation),它是否会使底层线程在等待的任务执行完成之前无法重用?
例如:
public async Task MethodAAsync()
{
// Execute some logic
var test = await MethodB();
// Execute remaining logic
}
在这里,由于我需要返回结果来进一步进行,我需要等待。但是,既然我们在等待,它是否会阻止底层线程生成的线程不用于执行任何任务?
但是,由于等待通常是No Op(No Operation),它是否使在执行等待的任务之前,底层线程不可重用完成?
我不确定你是从哪里得到这些信息的,但await
肯定不是一个无操作。例如,在Task
上调用await
将调用对Task.GetAwaiter
的逻辑调用,其中TaskAwaiter
必须实现INotifyCompletion
或ICriticalNotifyCompletion
接口,这"告诉"编译器如何调用延续(第一个await
之后的所有内容)。
async-await
的完整结构将您的调用转换为状态机,这样,当状态机命中第一个await
时,它将首先检查被调用的方法是否已完成,如果未完成,则将注册该方法调用的延续和返回。稍后,一旦该方法完成,它将重新进入状态机以完成该方法。从逻辑上讲,这就是await
被击中后的线条。
但是,既然我们在等待,它是否会阻塞底层线程结果线程没有被用来执行任何任务?
不,只创建一个完整的机制来阻止调用线程是没有用的。async-await
允许您将调用线程实际返回给调用者,这允许调用者在同一线程上继续执行,而运行时负责排队和调用完成。
简而言之,不,它不会阻塞线程。
更多信息:http://blog.stephencleary.com/2013/11/there-is-no-thread.html
线程有一个本地任务队列。一旦它到达一个await
,它就会从它的队列中获取另一个Task(假设它堆栈中的所有方法都是awaited
)。如果队列为空,它将尝试从全局队列中获取Task;如果队列也为空,线程将尝试从另一个线程自己的本地队列中获取Task。在一个简单的程序中,所有线程都可能"退出任务"——线程将保持空闲,直到其中一个任务返回。