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