我读过很多文章说async / await没有创建额外的线程。 但是Visual Studio的调试模式中的输出和线程窗口的消息却反过来说。
我用一些代码创建了一个非常简单的Windows窗体示例;
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");
}
我在debuging模式下启动app,我通过单击Debug工具栏上的暂停按钮暂停它。线程窗口显示只有一个主线程,到目前为止是正常的。
然后我点击按钮执行methodAsync
。当它完成DownloadString时,我再次暂停app,然后我在Thread窗口中看到了几个额外的线程。
大约10秒后,输出窗口显示消息"The thread xxx has exited with code 0 (0x0)"
。
将WebClient.DownloadStringTaskAsync
替换为await Task.Delay(xxx)
时的结果相同
我想知道async / await是否确实创建了新线程。
任何解释?
答案 0 :(得分:1)
async
和await
只是生成方法awaitable的关键字,然后允许您异步等待它并继续执行。 Tasks是表示方法执行的异步结果的底层框架元素,TaskScheduler负责协调Tasks的执行,这可能涉及使用线程池,创建新线程, Windows上的默认任务计划程序通常使用线程池来执行任务。
答案 1 :(得分:0)
WebClient.DownloadStringTaskAsync方法使用Task-based Asynchronous Pattern并使用从线程池自动分配的资源线程资源。
实现TAP方法时,可以确定异步位置 执行发生。您可以选择在线程上执行工作负载 pool,使用异步I / O实现它(不受绑定 线程为大多数操作的执行),在一个上运行它 特定线程(如UI线程),或使用任意数量的 潜在的背景。
正如您在方法定义中所看到的,它有一个属性ExternalThreading = true
,表示它可能会在外部线程上分配资源。