等待完全阻塞线程

本文关键字:线程 等待 | 更新日期: 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必须实现INotifyCompletionICriticalNotifyCompletion接口,这"告诉"编译器如何调用延续(第一个await之后的所有内容)。

async-await的完整结构将您的调用转换为状态机,这样,当状态机命中第一个await时,它将首先检查被调用的方法是否已完成,如果未完成,则将注册该方法调用的延续和返回。稍后,一旦该方法完成,它将重新进入状态机以完成该方法。从逻辑上讲,这就是await被击中后的线条。

但是,既然我们在等待,它是否会阻塞底层线程结果线程没有被用来执行任何任务?

不,只创建一个完整的机制来阻止调用线程是没有用的。async-await允许您将调用线程实际返回给调用者,这允许调用者在同一线程上继续执行,而运行时负责排队和调用完成。

简而言之,不,它不会阻塞线程。

更多信息:http://blog.stephencleary.com/2013/11/there-is-no-thread.html

线程有一个本地任务队列。一旦它到达一个await,它就会从它的队列中获取另一个Task(假设它堆栈中的所有方法都是awaited)。如果队列为空,它将尝试从全局队列中获取Task;如果队列也为空,线程将尝试从另一个线程自己的本地队列中获取Task。在一个简单的程序中,所有线程都可能"退出任务"——线程将保持空闲,直到其中一个任务返回。