【问题标题】:async/await create new thread, output window show thatasync/await 创建新线程,输出窗口显示
【发布时间】:2018-06-30 05:10:50
【问题描述】:

我读过很多文章说 async/await 不会创建额外的线程。 但是 Visual Studio 调试模式下输出和线程窗口的消息却相反。

我用一些代码创建了一个非常简单的示例窗体;

private void button2_Click(object sender, EventArgs e)
{
    Task t = methodAsync();
    //t.Wait();
}
async Task methodAsync()
{
    Console.WriteLine($"==before DownloadStringTaskAsync");
    using (var wc = new System.Net.WebClient())
    {
        string content = await wc.DownloadStringTaskAsync("https://stackoverflow.com");
    }
    Console.WriteLine($"==after DownloadStringTaskAsync");
}

我在调试模式下启动应用程序,我通过单击调试工具栏上的暂停按钮来暂停它。线程窗口显示只有一个主线程,目前正常。

然后我点击按钮执行methodAsync。完成 DownloadString 后,我再次暂停应用程序,然后在线程窗口中看到几个附加线程。

大约 10 秒后,输出窗口显示消息 "The thread xxx has exited with code 0 (0x0)"

当我将WebClient.DownloadStringTaskAsync 替换为await Task.Delay(xxx) 时,结果相同 我想知道 async/await 是否真的创建了新线程。

有什么解释吗?

【问题讨论】:

  • 异步工作通常会在不同的线程上运行,但如果您不使用 ConfigureAwait(false),它将在原始线程上恢复。它正在从池中抓取一个线程。我不确定这是否是您所说的“创建线程”。
  • 你读到的和你理解的不一定是一回事。 await-async 并不自动意味着在“新线程”中运行此任务,在某些情况下它会在某些情况下不会。要理解的想法是异步与另一个线程上的并发不同。
  • @Fabjan 并非总是如此。并非所有异步任务都需要在线程池中的线程上运行。看看there is no thread 以获得有趣的阅读。
  • 如果您还不知道,请查看“调试”>“窗口”>“任务”窗格。
  • @fabjan 题外话,你的断言是不正确的,我只是指出来。

标签: c# asynchronous threadpool


【解决方案1】:

WebClient.DownloadStringTaskAsync 方法使用Task-based Asynchronous Pattern 并使用从线程池中自动分配的资源线程资源。

当你实现一个 TAP 方法时,你可以确定在哪里异步 执行发生。您可以选择在线程上执行工作负载 池,通过使用异步 I/O 来实现它(不绑定到一个 执行大部分操作的线程),在 特定线程(如 UI 线程),或使用任意数量的 潜在的上下文。

正如您在方法定义中看到的,它有一个属性ExternalThreading = true,表明它可能会在外部线程上分配资源。

【讨论】:

【解决方案2】:

asyncawait 只是创建方法awaitable 的关键字,然后允许您异步等待它并继续执行。 Tasks是底层框架元素,代表方法执行的异步结果,TaskScheduler负责协调Tasks的执行,可能涉及到使用线程池、创建新线程等。默认Windows 上的任务调度程序一般使用线程池来执行任务。

【讨论】:

    猜你喜欢
    • 2015-01-31
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    相关资源
    最近更新 更多