【问题标题】:Thread blocked after await等待后线程阻塞
【发布时间】:2015-04-23 14:54:52
【问题描述】:

使用此代码:

    static void Main(string[] args)
    {
        Console.WriteLine("Main Thread Pre - " + GetNativeThreadId(System.Threading.Thread.CurrentThread));
        Task.Run(() => AsyncMethod()).Wait();
        Console.WriteLine("Main Thread Post - " + GetNativeThreadId(System.Threading.Thread.CurrentThread));
        Console.ReadKey();
    }

    static async Task AsyncMethod()
    {
        Console.WriteLine("AsyncMethod Thread Pre - " + GetNativeThreadId(System.Threading.Thread.CurrentThread));
        await Task.Delay(4000).ConfigureAwait(false);
        Console.WriteLine("AsyncMethod Thread Post - " + GetNativeThreadId(System.Threading.Thread.CurrentThread));
    }

输出是:

Main Thread Pre - 8652
AsyncMethod Thread Pre - 4764
AsyncMethod Thread Post - 1768
Main Thread Post - 8652

使用并发可视化工具,我可以看到在 4 秒延迟期间,线程 4764 卡在同步中。它最终在关闭时被主线程解除阻塞。

线程 4764 一旦碰到await,不应该返回到ThreadPool 吗? (话虽这么说,我不知道并发可视化器中会是什么样子)

【问题讨论】:

  • 您能否在不借助并发可视化工具的情况下演示任何类型的问题?
  • 不,我不能。我这样做是为了看看并发可视化器中等待的线程是什么样子的,并且惊讶地发现它在等待后位于同步类别中。要么我对异步的理解不正确,要么我误解了并发可视化工具告诉我的内容。我想我只是在确认线程 4764 在等待时实际上应该返回到 ThreadPool。
  • 任务线程被延迟,但延迟调用仍在内部运行计时器,因此正在工作。延迟不是调度延迟。
  • 那么在延迟完成之前阻止 4764 是否有意义?

标签: c# multithreading async-await


【解决方案1】:

线程 4764 一旦遇到 await 不应该返回到 ThreadPool 吗?

是的。确实如此。

(话虽这么说,我不知道并发可视化器内部会是什么样子)

这很容易检查。只需在线程池中显式执行一些代码,然后看看该线程在不忙时在可视化器中的样子。

例如:

ThreadPool.QueueUserWorkItem(o =>
    {
        Console.WriteLine("worker: " + GetNativeThreadId(System.Threading.Thread.CurrentThread));
        Thread.Sleep(250);
    });

(我添加了睡眠,因此它更容易在可视化器中显示为已完成某事:))。

当你这样做时,你会发现它看起来就像你看到的一样。 :)


当我运行它时,线程池甚至使用了与原始Task 相同的工作线程。您可以看到线程池工作线程在等待更多工作时处于Synchronization 状态。

这是有道理的。在抽象层面上,线程池在做什么?关键在于它拥有已经存在的线程。但是你不希望这些线程真正工作,除非他们有工作要做。那会无缘无故地消耗CPU时间。因此,它们会等待同步对象。

当某些东西(比如Task)想要使用一个时,它会将一个工作项排队,然后线程池会向它发出有事要做的线程发出信号。这会唤醒线程,完成它的工作,然后再次阻塞同步对象,等待其他操作。

如果您检查相关线程的调用堆栈,您会看到工作线程正在等待对 WaitForSingleObject() 的调用,并且您会看到线程池最终使用 ReleaseSemaphore() 解除阻塞线程。

正如您所见,这显示为线程池线程的Synchronization 状态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    • 2010-12-21
    • 2021-12-12
    • 1970-01-01
    相关资源
    最近更新 更多