await是否完全阻塞线程?

问题描述 投票:0回答:3

当我们在代码中使用

await
时,通常等待者会捕获上下文,并在等待的任务成功完成时将其用作回调。但是,由于
await
通常是 No-Op(无操作),这是否会使底层线程在等待的任务执行完成之前无法重用?

例如:

public async Task MethodAAsync()
{
    // Execute some logic
    var test = await MethodB();
    // Execute remaining logic
}

在这里,由于我需要返回结果才能进一步进行,因此我需要等待。但是,由于我们正在等待,它是否会阻塞底层线程导致线程不被用于执行任何任务?

c# multithreading asynchronous async-await
3个回答
11
投票

但是,由于await一般是No-Op(无操作),它是否使得 在执行等待的任务之前,底层线程不可重用 完成了吗?

我不确定您从哪里获得此信息,但

await
肯定不是无操作。例如,在
await
上调用
Task
将调用对
Task.GetAwaiter
的逻辑调用,其中
TaskAwaiter
必须实现
INotifyCompletion
ICriticalNotifyCompletion
接口,该接口告诉编译器如何调用延续(第一个
await
之后的所有内容)。

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

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

不,创建一个完整的机制只是为了阻塞调用线程是没有用的。

async-await
允许您实际将调用线程返回给调用者,从而允许它继续在同一线程上执行,而运行时则负责排队和调用完成。


4
投票

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

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


-1
投票

线程有一个本地任务队列。一旦它遇到

await
,它将从队列中拾取另一个任务(假设其堆栈上的所有方法都是
awaited
)。如果队列为空,它将尝试从全局队列中获取任务,如果队列也为空,则线程将尝试从另一个线程自己的本地队列中获取任务。在一个简单的程序中,所有线程都可能“脱离任务” - 线程将保持空闲状态,直到其中一个任务返回。

© www.soinside.com 2019 - 2024. All rights reserved.