Vin*_*cio 2 c# asynchronous async-await
来自MSDN:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
我从"异步和等待关键字不会导致创建其他线程"中得出的结论是它只使用已经从线程池创建的线程
不,这根本不是真的.async并且await不要在语言级别使用线程池.使用async/await编写程序是完全可能的,它只使用初始的"主"线程.
这并不意味着一切都会发生在一个线程上 - 只是async/await不会强制创建额外的线程.编译器本身不会生成任何代码来执行此操作.这完全取决于你正在等待的东西.例如,您可以使用任务来执行任务Task.Run,该任务将(通常)使用线程池,您可以等待它.或者你可以等待调用的结果Task.Delay,这本身不会启动任何线程,只是安排在未来完成任务.或者您可以使用异步IO,它可能使用IO完成端口,但实际上不会涉及另一个运行任务"活动"的大部分时间的线程.
一个设计良好的awaitable(如果你使用内置的东西,这将包括你)将安排延续(所有的代码后await),作为你在你开始等待,除非你明确已经相同的上下文告诉它不要."上下文"可能意味着您回到同一个线程(例如在UI中)但可能不会(例如在线程池上下文中,延续运行的线程池线程无关紧要).
在我看来,值得进一步了解异步真正做什么.围绕这个有很多资源,免费和付费墙后面: