源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

解析使用enumerator模式简化异步操作的详解

  • 时间:2021-01-13 20:50 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:解析使用enumerator模式简化异步操作的详解
[b]先看一段同步代码: [/b]public int SumPageSizes(IList<Uri> uris) {     int total = 0;     foreach (var uri in uris) {         statusText.Text = string.Format("Found {0} bytes ...", total);         var data = new WebClient().DownloadData(uri);         total += data.Length;     }     statusText.Text = string.Format("Found {0} bytes total", total);     return total; } 这段代码比较简单,使用同步方式一个一个的获取Uri的Data,然后进行统计。 [b]如果要使用异步方式一个一个的统计,那应该如何计算呢? [/b]我以前演示过一段丑陋的代码大致如下:   WebClient webClient = new WebClient();  webClient.DownloadDataCompleted += (s, e) =>  {      // 使用A对象,做些事情。      WebClient webClient2 = new WebClient();      webClient2.DownloadDataCompleted += (s2, e2) =>      {          //使用B对象,做些事情。         // 递归的去 DownloadDataAsync。      };      webClient2.DownloadDataAsync(new Uri("B 的地址"));  };  webClient.DownloadDataAsync(new Uri("A 的地址")); 当然如果你确定只有两个地址的话,这种方法未尝不可。如果有多个地址的话,则必须递归的调用了。 如何使用Enumerator来简化异步操作: public void SumPageSizesAsync(IList<Uri> uris) {     SumPageSizesAsyncHelper(uris.GetEnumerator(), 0); } private void SumPageSizesAsyncHelper(IEnumerator<Uri> enumerator, int total) {     if (enumerator.MoveNext()) {         statusText.Text = string.Format("Found {0} bytes ...", total);         var client = new WebClient();         client.DownloadDataCompleted += (sender, e) => {             SumPageSizesAsyncHelper(enumerator, total + e.Result.Length);         };         client.DownloadDataAsync(enumerator.Current);     }     else {         statusText.Text = string.Format("Found {0} bytes total", total);         enumerator.Dispose();     } } 通过SumPageSizesAsyncHelper ,可以实现异步调用A->异步调用B->异步调用C..的方式。 首先解释下为什么可以,假设uris 有A,B,C. SumPageSizesAsyncHelper(uris.GetEnumerator(), 0); 方法先调用A,因为A后面还有B,所以enumerator.MoveNext()返回True, 接着在DownloadDataCompleted事件结束后,调用B,同样,因为B后面还有C, 所以enumerator.MoveNext() 继续返回True,接着在DownloadDataCompleted事件后调用C。 在调用C结束后,因为C后面没有了,所以enumerator.MoveNext() 返回False, 也可以认为全部都下载完毕了。所以返回最终的结果。 [img]http://files.jb51.net/file_images/article/201305/20130513161601125.png[/img]   [img]http://files.jb51.net/file_images/article/201305/20130513161601126.png[/img] [b]如果使用async 和await来实现的话,代码如下:[/b] public async Task<int> SumPageSizesAsync2(IList<Uri> uris) {     int total = 0;     Char charText = 'A';     foreach (var uri in uris)     {        var data = await new WebClient().DownloadDataTaskAsync(uri);         total += data.Length;         Console.WriteLine("Thread Id: {0}:调用{1}的地址 Found {2} bytes...{3}",             Thread.CurrentThread.ManagedThreadId, charText, total, DateTime.Now);         charText = Convert.ToChar(charText + 1);     }     Console.WriteLine("Thread Id: {0}:全部完成,Found {1} bytes total {2}",         Thread.CurrentThread.ManagedThreadId, total, DateTime.Now);     return total; }
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部