您的位置:首页 > 编程语言 > C#

C#中的async与await

2016-06-28 14:59 232 查看
在.NET4.5或者说C#5.0中引入了两个新的关键字:
async
await
;都说这两个关键字简化了异步编程,那么我们来看看他们到底什么如何工作的~

异步与等待

异步方法通常会包括一个或者多个
await
关键字,但是缺少
await
关键字并不会导致编译器错误;如果异步方法未使用await关键字标记悬挂点,不管异步修饰符如何,那么该异步方法将作为同步方法执行;但编译器将会发出一个警告(warning)。

如果使用Async或者async修饰符指定某种方法为异步方法,则会启用一下两种功能:

标记的异步方法可以使用await来指定悬挂点(C#中);await 运算符通知编译器异步方法只有直到等待的异步过程完成才能继续通过该点; 同时,控件返回至异步方法的调用者。

await 表达式中异步方法的挂起不能使该方法退出,并且 finally 块不会运行。

标记异步的方法本身可以通过调用它的方法等待(我的理解是递归调用)。

返回类型

使用这两个关键字的返回类型为:

如果你的方法有操作数为 TResult 类型的返回语句,则为 Task。

如果你的方法没有返回语句或具有没有操作数的返回语句,则为 Task。

如果你编写的是异步事件处理程序,则为 Void。

线程

MSDN官方文档中说明:

The async and await keywords don’t cause additional threads to be created.Async methods don’t require multithreading because an async method doesn’t run on its own thread.

这两个关键字不会创建新的线程;异步方法不需要多线程,因为异步方法不会在自己的线程上运行。

The method runs on the current synchronization context and uses time on the thread only when the method is active.

当方法运行时,异步方法将在当前的同步上下文(SynchronizationContext)运行并使用线程上的时间。

到底有没有开辟新线程,这篇博客进行了分析,作者的观点是开没开辟新线程得看情况,总体来说就是SynchronizationContext这个东西在搞事,一般来说,在控件中SynchronizationContext管理的UI线程是唯一的,而如果是线程池就是一组线程,可以是任意一个线程来完成任务。

总结

使用了
async
await
关键字的异步方法中,除了
await
关键字修饰的方法以外,其他的代码运行都是同步的;

await 关键字只是一个承诺,使用了await标记的Task方法,那么就执行这个方法获得返回值,await后面的代码全部委托在这个方法completed之后执行,再返回给方法调用者;

最后其实我还是没有弄懂到底有没有在使用winform的时候使用多线程,按照MSDN的说法是没有,也不需要(如果我翻译对的话);但是事实感觉是有,所以我怀疑我的英语还有待提高~~~

参考博客文章

由于最后我的结论还不怎么确定,所以将我参考的博客放上来记录:

多线程之旅:解读async和await(描述了await的内部实现机制)

await之后的线程问题(类比了winform,console与webpage的区别)

说说C#的async和await(我比较同意这个作者的简洁说法)

使用 Async 和 Await 的异步编程(C# 和 Visual Basic)(MSDN官方说法)

补充

由于我自己也是半吊子,所以这个只是记录参考,如果你知道他们的原理一定要告诉小弟,不胜感激!~

纠正

今天又在各种博客上逛,偶然间发现的了上面我的观点或者说我看到的博客中有点观点是对的,MSDN还是正确的,是我们理解错误了!

首先,async与await关键字本身并不会产生多线程;

await 不会开启新的线程,当前线程会一直往下走直到遇到真正的Async方法(比如说HttpClient.GetStringAsync),这个方法的内部会用Task.Run或者Task.Factory.StartNew 去开启线程。也就是如果方法不是.NET为我们提供的Async方法,我们需要自己创建Task,才会真正的去创建线程。(引用自async & await 的前世今生(Updated)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: