我已经知道可以async-await
保留线程上下文,还可以处理异常转发等(这很有帮助)。
但是,请考虑以下示例:
/*1*/ public async Task<int> ExampleMethodAsync()
/*2*/ {
/*3*/ var httpClient = new HttpClient();
/*4*/
/*5*/ //start async task...
/*6*/ Task<string> contentsTask = httpClient.GetStringAsync("http://msdn.microsoft.com");
/*7*/
/*8*/ //wait and return...
/*9*/ string contents = await contentsTask;
/*10*/
/*11*/ //get the length...
/*12*/ int exampleInt = contents.Length;
/*13*/
/*14*/ //return the length...
/*15*/ return exampleInt;
/*16*/ }
如果async
方法(httpClient.GetStringAsync
)是IO操作(如上面的示例中所示),那么-我得到了这些东西:
TaskCompletionSource
而不打开新线程)但是如果不是httpClient.GetStringAsync
(IO操作)而不是(独立线程上的大量计算绑定操作)的任务,CalcFirstMillionsDigitsOf_PI_Async
该怎么办?
看来我在这里获得的唯一收获是:
但是我还有另一个线程(并行线程)来执行操作。并且cpu在主线程和操作之间切换。
我的诊断是否正确?
实际上,在两种情况下,您都只能获得第二套优势。await
不会启动任何东西的异步执行,它只是编译器的一个关键字,用于生成用于处理完成,上下文等的代码。
您可以在“ “使用等待调用方法”中找到对此的更好解释。斯蒂芬·图布(Stephen Toub)
由异步方法本身决定如何实现异步执行:
在每种情况下,都是释放线程(如果使用了线程)的特定实现。TaskScheduler在Task完成执行时自动释放线程,因此无论如何情况1和2都会获得此功能。
在回调的情况3下会发生什么,取决于如何进行回调。大多数情况下,回调是在某个外部库管理的线程上进行的。在这种情况下,您必须快速处理回调并返回以允许库重用该方法。
编辑
使用反编译器,可能会看到它GetStringAsync
使用了第三个选项:它创建一个TaskCompletionSource,当操作完成时会发出信号。执行该操作委托给HttpMessageHandler。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句