AsyncEnumerator对EAP的支持

去年在异步编程中开始使用Wintellect's .NET Power Threading Library中的AsyncEnumerator,这个库通过将程序员较陌生的异步编程模型转化为程序员较熟悉的同步编程模型来实现异步操作,较大的改善了异步代码的易写、易读、易维护性。

目前对AsyncEnumerator介绍的文章已经比较多了,但集中于APM(Asynchronous Programming Model)模式中的应用,而.NET中,特别是Silverlight中还有很多对象是使用EAP(Event-based Asynchronous Pattern),对应的EAP与AsyncEnumerator结合的文章与例子很少,加上Jeffrey Richter不喜欢EAP模型,让我一度以为AsyncEnumerator不支持,于是自己去实现了EAP和AsyncEnumerator的结合。后来项目后期对代码重构时,有时间就再仔细看了看Power Threading的实现,发现其本身对EAP的支持是有封装的。下面是基于AsyncEnumerator使用Silverlight进行Socket通信的例子(Silverlight的Socket只有EAP模型):

SocketAsyncEventArgs socketEventArg =  new SocketAsyncEventArgs();
socketEventArg.SocketClientAccessPolicyProtocol = SocketClientAccessPolicyProtocol.Tcp;
DnsEndPoint host =  new DnsEndPoint(HtmlPage.Document.DocumentUri.Host, Configurations.PORT);
socketEventArg.RemoteEndPoint = host;
AsyncEnumerator asyncEnum =  new AsyncEnumerator();
EventApmFactory<SocketAsyncEventArgs> eventApmFactory 
    =  new EventApmFactory<SocketAsyncEventArgs>();
// 异步代码组织在GetEnumerator()中
// IEnumerator<int> GetEnumerator(SocketAsyncEventArgs e,AsyncEnumerator ae){...}
var enumerator = GetEnumerator(socketEventArg,asyncEnum);
EventHandler<SocketAsyncEventArgs> eventHandler = 
    eventApmFactory.PrepareOperation(asyncEnum.End()).EventHandler;
socketEventArg.Completed += eventHandler;
asyncEnum.BeginExecute(enumerator, asyncEnum.EndExecute); 

其中关键的代码是: 

//  用EventApmFactory来创建一个Handler,这个Handler在每次事件触发时
//  调用asyncEnum.End(),将执行控制交还Enumerator,
//  Enumerator接着上次yield return之后的地方执行
EventHandler<SocketAsyncEventArgs> eventHandler = 
    eventApmFactory.PrepareOperation(asyncEnum.End()).EventHandler;
socketEventArg.Completed += eventHandler; 

这个代码比我自己的EAP封装代码要简化很多,此外,Jeffrey在BLog中对Task与AsyncEnumerator的结合做了说明:

private  static IEnumerator<Int32> AsyncEnumeratorAndTasks(AsyncEnumerator ae) {
    var t =  new Task<DateTime>(() => { Thread.Sleep( 10000);  return DateTime.Now; });
   t.Start();
 
    //  The Task tells the AsyncEnumerator when it is done
   
//  If you don’t need to identify the Task, you can pass ‘null’ instead of ‘task’
   t.ContinueWith(task => ae.End()(task));
 
    yield  return  1;       //  Waits for the 1 Task to complete
 
   
//  You MUST call DequeueAsyncResult to Remove the entry form the AsyncEnumerator object’s collection
   
//  Casting the return value and assigning to ‘t’ is not necessary; since ‘t’ already refer to the same Task object
   t = (Task<DateTime>) ae.DequeueAsyncResult();        
 
   Console.WriteLine(t.Result);      //  Shows the DateTime when the Task completed
}

参见:http://www.wintellect.com/CS/blogs/jeffreyr/archive/2009/10/12/using-net-4-0-tasks-with-the-asyncenumerator.aspx  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值