来自MSDN:
async和await关键字不会导致其他线程 创建。异步方法不需要多线程,因为异步 方法不会在自己的线程上运行。该方法在当前运行 同步上下文并仅在线程上使用时间 方法有效。
我从“async和await关键字不会导致创建额外的线程”中得到的结果是它只是使用已经从线程池创建的线程,这很好,但我理解的是“使用时间”在方法处于活动状态时的线程上。“
这是否意味着当我等待任务时,任务“移动”到当前线程还是将结果编组回当前线程?如果查看输出,结果将返回到不同的线程ID,但在完成后在原始线程上完成。我想我错过了这两次行动的“介于两者之间”。
void Main()
{
var tasks = new List<Task<byte[]>>();
Console.WriteLine ("Starting on Managed Thread ID {0}, Background {1}, Pool {2}\n",
Thread.CurrentThread.ManagedThreadId,
System.Threading.Thread.CurrentThread.IsBackground,
System.Threading.Thread.CurrentThread.IsThreadPoolThread);
for (int i = 0; i < 5; i++)
{
tasks.Add(WriteFile(@"D:\Temp\" + i + ".txt", new String('*', i)));
}
Console.WriteLine ("Before Wait()ing on Managed Thread ID {0}, Background {1}, Pool {2}",
Thread.CurrentThread.ManagedThreadId,
System.Threading.Thread.CurrentThread.IsBackground,
System.Threading.Thread.CurrentThread.IsThreadPoolThread);
Task.WhenAll(tasks).Wait();
Console.WriteLine ("Completed on Managed Thread ID {0}, Background {1}, Pool {2}",
Thread.CurrentThread.ManagedThreadId,
System.Threading.Thread.CurrentThread.IsBackground,
System.Threading.Thread.CurrentThread.IsThreadPoolThread);
}
async Task<byte[]> WriteFile(string path, string text)
{
FileStream fs = new FileStream(path, FileMode.Create);
try
{
Console.WriteLine ("Writing to file " + path + " . Managed Thread ID {0}, Background {1}, Pool {2}",
Thread.CurrentThread.ManagedThreadId,
System.Threading.Thread.CurrentThread.IsBackground,
System.Threading.Thread.CurrentThread.IsThreadPoolThread);
var bytes = Encoding.Unicode.GetBytes(text);
await fs.WriteAsync(bytes, 0, bytes.Length);
Console.WriteLine ("Finished writing to file " + path + ". Managed Thread ID {0}, Background {1}, Pool {2}",
Thread.CurrentThread.ManagedThreadId,
System.Threading.Thread.CurrentThread.IsBackground,
System.Threading.Thread.CurrentThread.IsThreadPoolThread);
return new byte[0];
}
finally
{
Console.WriteLine ("Finally! " + path + ". Managed Thread ID {0}, Background {1}, Pool {2}\n",
Thread.CurrentThread.ManagedThreadId,
System.Threading.Thread.CurrentThread.IsBackground,
System.Threading.Thread.CurrentThread.IsThreadPoolThread);
fs.Dispose();
}
}
输出:
Starting on Managed Thread ID 46, Background True, Pool False
Writing to file D:\Temp\0.txt . Managed Thread ID 46, Background True, Pool False
Finished writing to file D:\Temp\0.txt. Managed Thread ID 12, Background True, Pool True
Finally! D:\Temp\0.txt. Managed Thread ID 12, Background True, Pool True
Writing to file D:\Temp\1.txt . Managed Thread ID 46, Background True, Pool False
Finished writing to file D:\Temp\1.txt. Managed Thread ID 12, Background True, Pool True
Finally! D:\Temp\1.txt. Managed Thread ID 12, Background True, Pool True
Writing to file D:\Temp\2.txt . Managed Thread ID 46, Background True, Pool False
Finished writing to file D:\Temp\2.txt. Managed Thread ID 12, Background True, Pool True
Finally! D:\Temp\2.txt. Managed Thread ID 12, Background True, Pool True
Writing to file D:\Temp\3.txt . Managed Thread ID 46, Background True, Pool False
Finished writing to file D:\Temp\3.txt. Managed Thread ID 24, Background True, Pool True
Finally! D:\Temp\3.txt. Managed Thread ID 24, Background True, Pool True
Writing to file D:\Temp\4.txt . Managed Thread ID 46, Background True, Pool False
Before Wait()ing on Managed Thread ID 46, Background True, Pool False
Finished writing to file D:\Temp\4.txt. Managed Thread ID 18, Background True, Pool True
Finally! D:\Temp\4.txt. Managed Thread ID 18, Background True, Pool True
Completed on Managed Thread ID 46, Background True, Pool False
答案 0 :(得分:7)
我从&#34;异步和等待关键字中获取的内容不会导致创建其他线程&#34;它只是使用已经从线程池
创建的线程
不,那根本不是真的。 async
和await
根本不在语言级别使用线程池。完全可以使用async / await编写程序,该程序仅使用初始&#34; main&#34;线程。
这并不意味着所有将发生在一个线程上 - 它只是异步/等待不要强制额外要创建的线程。编译器本身不会生成任何代码来执行此操作。这完全取决于你正在等待什么。例如,您可以使用Task.Run
对任务进行任务,这将(通常)使用线程池,您可以等待它。或者你可以等待调用Task.Delay
的结果,await
本身并不启动任何线程,只是安排将来完成任务。或者您可以使用异步IO,它可能使用IO完成端口但实际上还没有涉及另一个运行的线程,大部分时间该任务都是活动的&#34;。< / p>
精心设计的等待(如果您使用内置的任何内容,这将包括您)将在与您在同一环境中的相同上下文中安排延续({{1}}之后的所有代码)你开始等待它,除非你特别告诉它不要。那&#34;上下文&#34;可能意味着你回到同一个线程(例如在UI中)但可能没有(例如在线程池上下文中,延续运行的线程池线程并不重要。)
在我看来,值得深入了解异步真正做什么。围绕这个有很多资源,免费和付费墙背后都有: