技术开发 频道

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

  CCR

  你可能要问,第三方的开发者都提供了这些改进异步编程的类库,难道微软就没有么?

      微软的CCR(Concurrency and Coordination Runtime)是为机器人开发平台中需要并行协作而开发的类库。下面我会先简单介绍一下CCR对并发编程的支持,然后介绍一下其对异步编程模型的简化。

  在CCR中有一个核心类型Dispatcher,每个Dispatcher都管理着一些线程,相当于一个线程池。与CLR的ThreadPool不同的是,每个Dispatcher都对应着一个自己的“线程池”,而每个CLR中只有一个ThreadPool。一般会将一个Dispatcher与一个DispatcherQueue绑定,任务会进入DispatcherQueue这个队列,然后Dispatcher管理的线程就会执行这个队列里的任务。从这一点看很像我们在上一篇已经接触过的IO完成端口的行为。

  CCR中对并发的实现应该算actor-based模型,熟悉Erlang的同学应该会很清楚这个东西。在CCR中,我们创建一个Port对象,这个对象就相当于一个actor,我们可以通过Port对象的Post方法向其发送消息,Post接收到消息后会将需要执行的任务推进相绑定的DispatcherQueue队列,然后由对应的Dispatcher调度线程去执行。代码如下所示:

using(Dispatcher dispatcher = new Dispatcher(0,"My ThreadPool Name"))

  {

  
//创建一个任务队列与一个Dispatcher绑定

  DispatcherQueue taskQueue
= new DispatcherQueue("task queue",dispatcher);

  Port sender
= new Port();

  
//创建一个接受者,监视sender

  Receiver receiver
= Arbiter.Receive(true, sender,delegate(String message) { Console.WriteLine(message);})

  
//该接受者接收到消息后会向taskQueue推入一个任务

  Arbiter.Active(taskQueue,receiver);

  
//发送消息

  sender.Post(
"Hello");

  }

  上面是使用CCR进行message-based并发编程,message-based的并发编程的好处是避免了Shared Memory,也就不需要锁机制了,简化了并发编程的模型。

  而CCR中还提供了FromIteratorHandler这么一个方法,其接受一个IEnumerable参数,表示IEnumerable里每一项都是都是一个操作。有了这个我们再和“神奇的yield”结合起来,又可以大大简化异步开发了:

1: public IEnumerator Download()

  
2: {

  
3: var resultPort = new Port();

  
4:

  
5: var request = WebRequest.Create("http://www.google.com");

  
6: request.BeginGetResponse(resultPort.Post,null);

  
7:

  
8: yield return resultPort.Receive();

  
9:

  
10: var response = request.EndGetResponse((IAsyncResult)resultPort.Test());

  
11:

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

  
13: {

  
14: var buffer = new byte[1024];

  
15:

  
16: stream.BeginRead(buffer,0,1024,resultPort.Post,null);

  
17:

  
18: yield return resultPort.Receive();

  
19:

  
20: var actualRead = stream.EndRead((IAsyncResult)resultPort.Test());

  
21:

  
22: Console.WriteLine(Encoding.Default.GetString(buffer,0,actualRead));

  
23: }

  
24: }

  然后使用下面的代码运行:

        1: Dispatcher dispatcher = new Dispatcher();

  
2: DispatcherQueue queue = new DispatcherQueue("download", dispatcher);

  
3: Arbiter.Activate(queue, Arbiter.FromIteratorHandler(Download));

 

  关于CCR更详细的资料参见这里。Jeffrey Ritcher也在MSDN杂志上有一篇文章介绍CCR,该文的示例代码中还有对各种异步IO的封装代码。

0
相关文章