手机
当前位置:查字典教程网 >编程开发 >C#教程 >解析使用enumerator模式简化异步操作的详解
解析使用enumerator模式简化异步操作的详解
摘要:先看一段同步代码:publicintSumPageSizes(IListuris){inttotal=0;foreach(varuriinu...

先看一段同步代码:

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,然后进行统计。

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

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

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,

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

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

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

如果使用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;

}

【解析使用enumerator模式简化异步操作的详解】相关文章:

c# 引用类型与值类型的区别详解

深入委托与多播委托的详解

深入C#任务管理器中应用程序选项隐藏程序本身的方法详解

深入C#判断操作系统类型的总结详解

解析XPath语法之在C#中使用XPath的示例详解

使用checked语句防止数据溢出的解决方法

解析C#中的装箱与拆箱的详解

解析Silverlight调用WCF/Rest异常的解决方法

C#词法分析器之词法分析的使用详解

C#使用DllImport调用非托管的代码的方法

精品推荐
分类导航