HTML5技术

C#与C++的发展历程第三 - C#5.0异步编程巅峰 - hystar

字号+ 作者:H5之家 来源:博客园 2016-01-15 10:03 我要评论( )

系列文章目录 1.C#与C++的发展历程第一 - 由C#3.0起 2.C#与C++的发展历程第二 - C#4.0再接再厉 3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰 C#5.0作为第五个C#的重要版本,将异步编程的易用度推向一个新的高峰。通过新增的async和await关键字,几乎可以

系列文章目录

1. C#与C++的发展历程第一 - 由C#3.0起

2. C#与C++的发展历程第二 - C#4.0再接再厉

3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰

 

C#5.0作为第五个C#的重要版本,将异步编程的易用度推向一个新的高峰。通过新增的async和await关键字,几乎可以使用编写同步代码的方式来编写异步代码。

本文将重点介绍下新版C#的异步特性以及部分其他方面的改进。同时也将介绍WinRT程序一些异步编程的内容。

 

C# async/await异步编程

写async异步编程这部分内容之前看了好多文章,反复整理自己的思路,尽力保证文章的正确性。尽管如此仍然可能存在错误,请广大园友及时指出,感谢感谢。

异步编程不是一个新鲜的话题,最早期的C#版本也内建对异步编程的支持,当然在颜值上无法与目前基于TAP,使用async/await的异步编程相比。异步编程要解决的问题就是许多耗时的IO可能会阻塞线程导致CPU空转降低效率,或者一个长时间的后台任务会阻塞用户界面。通过将耗时任务异步执行来使系统有更高的吞吐量,或保持界面的响应能力。如界面在加载一幅来自网络的图像时,还运行用户进行其他操作。

按前文惯例先上一张图通览一下TAP模式下异步编程的方方面面,然后由异步编程的发展来讨论一下TAP异步模式。

图1

APM

C# .NET最早出现的异步编程模式被称为APM(Asynchronous Programming Model)。这种模式主要由一对Begin/End开头的组成。BeginXXX方法用于启动一个耗时操作(需要异步执行的代码段),相应的调用EndXXX来结束BeginXXX方法开启的异步操作。BeginXXX方法和EndXXX方法之间的信息通过一个IAsyncResult对象来传递。这个对象是BeginXXX方法的返回值。如果直接调用EndXXX方法,则将以阻塞的方式去等待异步操作完成。另一种更好的方法是在BeginXXX倒数第二个参数指定的回调函数中调用EndXXX方法,这个回调函数将在异步操作完成时被触发,回调函数的第二个参数即EndXXX方法所需要的IAsyncResult对象。

.NET中一个典型的例子如System.Net命名空间中的HttpWebRequest类里的BeginGetResponse和EndGetResponse这对方法:

IAsyncResult BeginGetResponse(AsyncCallback callback, object state) WebResponse EndGetResponse(IAsyncResult asyncResult)

由方法声明即可看出,它们符合前述的模式。

APM使用简单明了,虽然代码量稍多,但也在合理范围之内。APM两个最大的缺点是不支持进度报告以及不能方便的“取消”。

 

EAP

在C# .NET第二个版本中,增加了一种新的异步编程模型EAP(Event-based Asynchronous Pattern),EAP模式的异步代码中,典型特征是一个Async结尾的方法和Completed结尾的事件。XXXCompleted事件将在异步处理完成时被触发,在事件的处理函数中可以操作异步方法的结果。往往在EAP代码中还会存在名为CancelAsync的方法用来取消异步操作,以及一个ProgressChenged结尾的事件用来汇报操作进度。通过这种方式支持取消和进度汇报也是EAP比APM更有优势的地方。通过后文TAP的介绍,你会发现EAP中取消机制没有可延续性,并且不是很通用。

.NET2.0中新增的BackgroundWorker可以看作EAP模式的一个例子。另一个使用EAP的例子是被HttpClient所取代的WebClient类(新代码应该使用HttpClient而不是WebClient)。WebClient类中通过DownloadStringAsync方法开启一个异步任务,并有DownloadStringCompleted事件供设置回调函数,还能通过CancelAsync方法取消异步任务。

 

TAP & async/await

从.NET4.0开始新增了一个名为TPL的库主要负责异步和并行操作的处理,目标就是使异步和并发操作有个统一的操作界面。TPL库的核心是Task类,有了Task几乎不用像之前版本的异步和并发那样去和Thread等底层类打交道,作为使用者的我们只需要处理好Task,Task背后有一个名为的TaskScheduler的类来处理Task在Thread上的执行。可以这样说TaskScheduler和Task就是.NET4.0中异步和并发操作的基础,也是我们写代码时不二的选择。

对于Task可以将其理解为一个包装委托对象(通常就是Action或Func对象)并执行的容器,从Task对象的创建就可以看出:

Action action = () => Console.WriteLine("Hello World"); Task task1 = new Task(action); Func<object, string> func = name => "Hello World" + name; Task<string> task2 = new Task<string>(func, "hystar" , CancellationToken.None,TaskCreationOptions.None );//接收object参数真蛋疼,很不容易区分重载,把参数都写上吧。

执行这个Task对象需要手动调用Start方法:

task1.Start();

这样task对象将在默认的TaskScheduler调度下去执行,TaskScheduler使用线程池中的线程,至于是新建还是使用已有线程这个对用户是完全透明的。还也可以通过重载函数的参数传入自定义的TaskScheduler。

关于TaskScheduler的调度,推荐园子里这篇文章,前半部分介绍了一些线程执行机制,很值得一度。

当我们用new创建一个Task对象时,创建的对象是Created状态,调用Start方法后将变为WaitingToRun状态。至于什么时候开始执行(进入Running状态,由TaskScheduler控制,)。Task的创建执行还有一种“快捷方式”,即Run方法:

Task.Run(() => Console.WriteLine("Hello World")); var txt = await Task<string>.Run(() => "Hello World");

这种方式创建的Task会直接进入WaitingToRun状态。

Task的其他状态还有RanToCompletion,Canceled以及Faulted。在到大RanToCompletion状态时就可以获得Task<T>类型任务的结果。如果Task在状态为Canceled的情况下结束,会抛出 OperationCanceledException。如果以Faulted状态结束,会抛出导致任务失败的异常。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 2年前端学习历程,与找不到工作的悲愤与吐槽!(100%真实经历,看博主怎么一步步走向失业) - 蒋启钲

    2年前端学习历程,与找不到工作的悲愤与吐槽!(100%真实经历,看博

    2017-03-29 11:00

  • 开源第三方登录组件OAuthLogin2.0 支持QQ,阿里巴巴,淘宝,京东,蘑菇街,有赞等平台 - 大壮他哥

    开源第三方登录组件OAuthLogin2.0 支持QQ,阿里巴巴,淘宝,京东,蘑菇街

    2017-01-20 15:00

  • 从零到百亿互联网金融架构发展史 - 纯洁的微笑

    从零到百亿互联网金融架构发展史 - 纯洁的微笑

    2017-01-14 13:00

  • 记一次企业级爬虫系统升级改造(四):爬取微信公众号文章(通过搜狗与新榜等第三方平台) - 彩色铅笔

    记一次企业级爬虫系统升级改造(四):爬取微信公众号文章(通过搜狗

    2017-01-12 10:01

网友点评
d