技术开发 频道

.NET开发中的异步编程:第三方类库

    【IT168  专稿】在前一篇文章中(.NET异步编程:使用CPS及yield实现异步)我们看到了一些关于CPS的讨论,并利用C# 2新增的迭代器yield来实现CPS的编码方式,简化异步编程。不过异步并不是你想象的那么简单,也不是我那个随手写的几行代码能够解决的,特别是当并发环境下你会看到到处是异常。所幸的是在.NET平台中已经有一些第三方类库能够简化我们的异步编程,而且还更可靠。在本文中我想介绍的第三方类库有三个:Jeffrey Ritcher的AsyncEnumerator,微软的CCR以及Microsoft Research的Rx。不过我这里只是浅尝辄止的介绍,要了解更多内容可以参照她们的官方文档,我在后面会列出链接。

  AsyncEnumerator

  把上一篇文章的代码改用AsyncEnumerator实现就是下面这个样子: 

       1: public IEnumerator Download(AsyncEnumerator ae)

  
2: {

  
3: var request = HttpWebRequest.Create("http://www.google.com");

  
4: request.BeginGetResponse(ae.End(),null);

  
5: yield return 1;

  
6: var response = request.EndGetResponse(ae.DequeueAsyncResult());

  
7: using(var stream = response.GetResponseStream())

  
8: {

  
9: stream.BeginRead(buffer,1,1024,ae.End(),null);

  
10: yield return 1;

  
11: var actualRead = stream.EndRead(ae.DequeueAsyncResult());

  
12: }

  
13: }

  
14:

  
15: public void btnDownload_Click(object sender,EventArgs e)

  
16: {

  
17: AsyncEnumerator ae = new AsyncEnumerator();

  
18: ae.EndExecute(ae.BeginExecute(Download(),null));

  
19: }

  可以看到,这里的代码几乎与上一篇文章使用yield实现异步的代码一模一样,实际上站在AsyncEnumerator背后的正是yield。但是AsyncEnumerator对异步的一些问题做了增强。比如大家经常碰到的在不是创建UI的线程里更新UI上的元素会抛出异常的问题在使用AsyncEnumerator中就不存在。所以对于上面的代码我们可以放心的在异步接收到服务器端返回的内容后更新UI上的元素:

  

       1: string content = Encoding.Default.GetString(buffer,0,actualRead);

  
2: this.txtContent.Text = content;

  

        关于这方面的细节你可以使用“SynchronizationContext”作为关键字搜索,MSDN杂志的二月刊上也有一篇相关文章:It's All About the SynchronizationContext

  AsyncEnumerator还有很多其他便利性,在本文我就不一一讨论了。感兴趣的可以去其官方网站,下载详细的示例。

  另外,虽然AsyncEnumerator使用同步方式的编写异步代码,样子看起来是同步的,但它并没有避免它异步的本质。异步的代码调试起来是非常困难的,你会发现执行流程乱序五章。而AsyncEnumerator对调试也提供了一些支持,让你调试的时候有一条线索可以跟踪。

0
相关文章