博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用enumerator模式简化异步操作
阅读量:7143 次
发布时间:2019-06-28

本文共 2386 字,大约阅读时间需要 7 分钟。

先看一段同步代码:

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; 
}

这段代码比较简单,使用同步方式一个一个的获取UriData,然后进行统计。

 

如果要使用异步方式一个一个的统计,那应该如何计算呢?

我以前演示过一段丑陋的代码大致如下:

 

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

也可以认为全部都下载完毕了。所以返回最终的结果。

 

 

 

如果使用async await来实现的话,代码如下:

 

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;

}

本文转自LoveJenny博客园博客,原文链接:http://www.cnblogs.com/LoveJenny/archive/2011/11/04/2235241.html,如需转载请自行联系原作者
你可能感兴趣的文章
input text 的事件及方法
查看>>
Sencha Touch+PhoneGap打造超级奶爸之喂养记(一) 源码免费提供
查看>>
libvirtVirsh
查看>>
PHP设计模式之策略模式
查看>>
以16进制打印出一块内存buff
查看>>
c语言学习之结构篇代码演示样例-输入n个同学的姓名,数学英语成绩,依照平均分从低到高排序并输出...
查看>>
Java中primitive type的线程安全性
查看>>
setAnimationStyle实现的popwindow显示消失的动画效果
查看>>
uva193 - Graph Coloring
查看>>
关于"The dependency was added by the project system and cannot be removed" Error
查看>>
php性能监测模块XHProf
查看>>
stm32之GPIO库函数开发
查看>>
在ASP.NET MVC中,使用Bundle来打包压缩js和css
查看>>
禁止执行某些讨厌的程序,如tadb.exe
查看>>
tomcat 7 下添加 shared/lib 文件夹
查看>>
Java集合---ConcurrentHashMap原理分析
查看>>
动画 -- 点击按钮 -- 顺时针旋转一圈
查看>>
执行计划中常见index访问方式(转)
查看>>
【java开发系列】—— struts2简单入门示例
查看>>
博客园“可运行"代码
查看>>