【问题标题】:Async/await: who is waiting/blocking?异步/等待:谁在等待/阻塞?
【发布时间】:2022-01-04 22:49:43
【问题描述】:

我正在尝试理解async/await 并阅读AsyncMethodBuilder 的源代码。我认为必须有一些代码,例如 xxx.Wait()xxx.WaitOnce() 等待任务完成。

但是,我在 AsyncMethodBuilder 类中没有找到这样的代码。

系统\运行时\compilerservices\AsyncMethodBuilder.cs https://referencesource.microsoft.com/#mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs,96

于是我一直在挖掘,试图阅读TaskTaskSchedulerThreadPoolTaskSchedulerThreadPool的源代码。

最后我得到了_ThreadPoolWaitCallback 的课程,但没有找到任何来电者。 https://referencesource.microsoft.com/#mscorlib/system/threading/threadpool.cs,d7b8a78b4dd14fd0

internal static class _ThreadPoolWaitCallback
{
    [System.Security.SecurityCritical]
    static internal bool PerformWaitCallback()
    {
        return ThreadPoolWorkQueue.Dispatch();
    }
}

另一个可能的代码在类SynchronizationContext,方法SetWaitNotificationRequired()

https://referencesource.microsoft.com/#mscorlib/system/threading/synchronizationcontext.cs,8b34a86241c7b423

 protected void SetWaitNotificationRequired()
    {
        ...
            RuntimeHelpers.PrepareDelegate(new WaitDelegate(this.Wait));
        ...

但是我不知道RuntimeHelpers.PrepareDelegate在做什么,这是一个native方法。

请给点建议。有Wait 吗?如果是,它在哪里?

【问题讨论】:

  • 所以您希望some thread 在等待Task 期间被阻止?
  • 我不太明白这个问题,但如果它有任何用处 - C# 编译器将 async/await 重写为状态机(它实际上只是一个 switch 语句),然后它将重复调用基于事件的方式。没有阻塞的线程/线程可以再次唤醒。
  • @LukeBriggs 是的,希望 OP 能够更清楚地说明他们的要求。问题似乎是“Wait 在哪里?”,它假设某处有一个Wait。恕我直言,更好的问题是“有Wait吗?如果有,它在哪里?”
  • @TheodorZoulias 是的,你是对的。我的问题正是你所说的。有Wait 吗?如果是,它在哪里?
  • @Dai 我认为你是对的。非常感谢

标签: c# async-await


【解决方案1】:

在正确实现的异步实现中:没有等待。相反,在链的底部,存在一些将创建一些异步源的代码,这可能是 TaskCompletionSource<T>IValueTaskSource[<T>] 或类似的东西 - 这允许该代码将该令牌存储在某处(例如,在队列、相关字典或 IOCP 的异步状态对象),并将 incomplete 任务返回给调用者。然后调用者发现它不完整,并注册一个“当你有答案时,这样做以重新激活我”回调。该调用代码现在完全展开,每一步都说“完成后,推到这里”,然后线程继续执行其他操作,例如为不同的请求提供服务。

在未来的某个时候(希望如此),结果会再次出现 - 再次通过 IOCP 或通过单独的 IO 读取器从某处拉取响应并将适当的项目从队列/相关字典中取出,并且说“结果是 {...}”(TrySetResult、TrySetException 等)。

在那段时间里没有线程被阻塞。也就是说,最终,async/await 的全部意义在于:释放线程,提高可扩展性。


在错误实现的异步系统中:任何事情都是可能的,包括异步同步、异步同步和其他一切。

【讨论】:

  • 有趣!你有什么资料可以解释这些考虑吗? (关于什么是正确 vs incorrect实现)
  • @XouDo 例如,当一个方法具有单独的非异步和异步版本时(例如Stream.ReadStream.ReadAsync),但如果async 版本从未实际使用@987654327 @ 而不是return Task.FromResult( this.Read(...) );,也称为“fake-async”。
猜你喜欢
  • 2016-03-13
  • 2011-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 2019-10-16
相关资源
最近更新 更多