【问题标题】:Does await completely block the thread?await 是否完全阻塞了线程?
【发布时间】:2016-01-10 13:05:00
【问题描述】:

当我们在代码中使用await 时,通常等待者捕获上下文并在等待的任务成功完成时将其用作回调。但是,由于await 通常是一个No-Op(无操作),它是否使底层线程在等待的任务执行完成之前不可重用?

例如:

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

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

【问题讨论】:

  • 我的理解是 Task 会作为 No.Op 继续执行,但是可以在底层线程中执行多个任务,因此不会被阻塞。
  • 如果它确实阻塞了,这个功能有什么好处?这相当于调用 .Result。

标签: c# multithreading asynchronous async-await


【解决方案1】:

但是,由于await通常是No.Op(No Operation),它是否使 在执行等待的任务之前,底层线程不可重用 完成了吗?

我不确定你从哪里得到这些信息,但await肯定不是无操作。例如,在Task 上调用await 将调用对Task.GetAwaiter 的逻辑调用,其中TaskAwaiter 必须实现INotifyCompletion 或ICriticalNotifyCompletion 接口,它告诉编译器如何调用延续(第一个 await 之后的所有内容。

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多