【问题标题】:async and await thread issue异步和等待线程问题
【发布时间】:2017-04-01 13:50:48
【问题描述】:

我编写了一个程序来检查我是否理解 async-await 的概念。

       static void Main(string[] args)
    {
        Run2().Wait();
    }

    static async Task DoAsyncWork()
    {
        await Task.Delay(2000);
    }

    static async Task Run2()
    {
        var tid = Thread.CurrentThread.ManagedThreadId;
        await DoAsyncWork();
        Console.WriteLine(tid == Thread.CurrentThread.ManagedThreadId);
    }

我有点迷茫,打印出来的是什么?

我认为我们无法保证会打印什么

我的解释: 当await DoAsyncWork 被调用时,控制返回到Main。 在DoAsyncWork 完成控制返回并在等待之后继续其余代码。 其余代码可以运行,我们无法保证女巫线程运行此代码。

其实: 我运行这段代码很多时间并得到False 打印。

【问题讨论】:

  • 你要问多少次同一个问题? stackoverflow.com/questions/40577858/…
  • 我们无法保证女巫线程运行此代码。 如果await 将安排继续而不是继续(如果看到已经完成的任务就会这样做),那么我们保证继续将在ThreadPool 线程之一上运行。和之前的await 一样,它不使用ThreadPool 线程,那么它保证线程会不同。
  • 你真的应该停止一次又一次地问同样的问题。最好阅读这篇文章:blog.stephencleary.com/2012/02/async-and-await.html

标签: c# async-await task-parallel-library


【解决方案1】:

await 将使用SynchronizationContext.Current 来确定如何执行延续代码。如果当前同步上下文中有一个值,并且同步上下文的特定实现最终会在特定线程上运行发送给它的所有代码,那么您将始终在同一个线程中运行代码。 (winforms 或 WPF 应用程序设置的同步上下文会执行此操作。)

如果没有同步上下文(在您的代码中就是这种情况),将使用默认值,它使用线程池,因此它最终可以在任何线程上运行。也有可能存在一个同步上下文集,它不一定在同一个线程上运行发送给它的所有代码。 (ASP 应用程序使用的同步上下文会执行此操作。)

由于在您的代码中没有同步上下文,因此将使用线程池,并且线程永远不会相同。如果您创建了一个消息循环,其中有一个同步上下文将消息定向到它(例如,在启动 winforms 或 WPF 应用程序时会发生)并从中调用Run2,那么线程将可靠地匹配。

【讨论】:

  • 那么如果在 await 关键字之前和之后的上下文是相同的,那么线程将是相同的?
  • @maz 如果您在await 之前没有默认上下文,则取决于将调用线程和上下文继续的上下文,假设await 有一些等待而不是已经完成的任务,在这种情况下将在当前线程中继续执行。
  • @PetSerAl 你能举个例子吗,假设上下文是asp上下文?
  • @maz 究竟是什么例子?而且我对 ASP 上下文实现细节也不是特别熟悉。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 2018-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多