CCR&迭代器

原文链接

CCR 以新颖的方式使用了C# 2.0语言的迭代器功能:程序员可以用顺序的方式来编写代码,迭代返回(yielding)CCR仲裁器或者其他的CCR Task,而不需要使用delegates来嵌套异步行为(也叫做回调)。多步的异步逻辑也可以被写到一个迭代方法里,从而极大的提高代码的可读性,维护异步行为,并且由于迭代返回不会阻塞操作系统线程,所以可以伸缩到百万级别的未决操作。

例18.

        void StartIterator()
        {
            // create an IterativeTask instance and schedule it
            Arbiter.Activate(_taskQueue,
                Arbiter.FromIteratorHandler(IteratorExample)
            );
        }
        /// 
        /// Iterator method scheduled by the CCR
        /// 
        IEnumerator
 
 
  
   IteratorExample()
        {
            // accumulator variable
            int totalSum = 0;
            Port
  
  
   
    portInt = new PortSet
   
   
    
    ();            
            // using CCR iterators we can write traditional loops
            // and still yield to asynchronous I/O !
            for (int i = 0; i < 10; i++)
            {
                // post current iteration value to a port
                portInt.Post(i);
                // yield until a delegate executes in some other thread 
                yield return Arbiter.Receive
    
    
     
     (false, portInt, delegate(int j)
                {
                    // this delegate can modify a stack variable, allowing it
                    // communicate the result back to the iterator method
                    totalSum += j;
                });
            }
            Console.WriteLine("Total:" + totalSum);
        }
    
    
   
   
  
  
 
 

在上面的例子中,StartIterator方法是用Arbiter类来从一个迭代delegate创建任务,然后用Arbiter.Activate提交任务给调度。第二个方法是迭代方法,迭代方法是指使用yield return或者yield break C#语句来控制执行的方法。迭代方法和普通C#方法的区别是返回值:

        IEnumerator
  
   IteratorExample()
        {

这个方法的返回值表明了这是一个在CCR ITask实例上的C#迭代器

重要:永远不要再迭代器中返回持久化的接收器。在上面的yield语句中,Arbiter.Receive的persist参数是false(第一个参数)。如果接收器是持久化的,yield永远不会被满足,所以迭代器会停止迭代,永远不会处理yield后的下一个语句。

通过本地变量隐式的传递参数

将CCR与CLR迭代器一起使用的好处来自于两个C#的语言特性:

  1. 匿名方法-我们已经在前面的例子中使用过这个特性,用来定义内联的delegate。
  2. 编译器“捕获”所有在匿名方法中引用的迭代方法里面的局部变量。这使得delegate可以使用这些定义在父方法中的局部变量。总是运行在其他线程中的delegate也可以将结果返回给父迭代器,而不需要任何的显式参数传递。
            // this delegate can modify a stack variable, allowing it
            // communicate the result back to the iterator method
            totalSum += j;

部分返回到协调原语

例19

        void StartIterator2()
        {
            Port
 
 
  
   portString = new Port
  
  
   
   ();
            Arbiter.Activate(
                _taskQueue,
                Arbiter.ReceiveWithIterator(false, portString, StringIteratorHandler)
            );
        }
        IEnumerator
   
   
    
     StringIteratorHandler(string item)
        {
            Console.WriteLine(item);
            yield break;
        }
   
   
  
  
 
 

上面的这个例子展示了如何指定一个迭代方法作为一个接收操作的结果(the outcome of a receive operation)。到现在为之,我们用于在仲裁器被满足时执行的方法都是传统的方法(methods)。Arbiter类包含一些方法,它们需要一个迭代器delegate(The Arbiter class contains methods that expect an iterator delegate for all the major coordination primitives (JoinReceiver, MultipleItemGather, Choice, Receiver, etc) giving the programmer the choice between regular methods or iterator methods for every CCR coordination primitive.)。仲裁器的实现依赖ITask而不是用户delegate,ITask隐藏了用户delegate的类型,所以仲裁器可以适应迭代或者非迭代方法。

例20.

        IEnumerator
 
 
  
   IteratorWithChoice()
        {            
            // create a service instance
            ServicePort servicePort = ServiceWithInterleave.Create(_taskQueue);
            
            // send an update request
            UpdateState updateRequest = new UpdateState();
            updateRequest.State = "Iterator step 1";
            servicePort.Post(updateRequest);

            string result = null;
            // wait for EITHER outcome before continuing
            yield return Arbiter.Choice(
                updateRequest,
                delegate(string response) { result = response; },
                delegate(Exception ex) { Console.WriteLine(ex); }
            );
            // if the failure branch of the choice executed, the result will be null
            // and we will terminate the iteration
            if (result == null)
                yield break;
            // print result from first request
            Console.WriteLine("UpdateState response:" + result);
            // now issue a get request
            GetState get = new GetState();
            servicePort.Post(get);
            // wait for EITHER outcome
            yield return Arbiter.Choice(
                get.ResponsePort,
                delegate(string response) { result = response; },
                delegate(Exception ex) { Console.WriteLine(ex); }
            );
            // print result from second request
            Console.WriteLine("GetState response:" + result);
        }
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值