Freigeben über


How to not dispatch work in CCR

Being new to the Robotics team also means I get a chance to do some beginner mistakes with CCR. Let's assume that you have a method that does a lot of work and you want to use CCR to do the work. Before using CCR your code would have looked like this:

    1:          private void ProcessWithoutCcr()
   2:          {
   3:              // Do Work
   4:              // Do a lot more work that takes a lot of time
   5:          }

If all the work you're doing is just taking time because it needs to use the CPU the method is actually OK. But if there are a lot of things working with files, network etc you want to use a series of yield returns to split up the execution. If you're not really interested in the result or the methods cannot fail you (as a beginner) wold maybe do something like this:

    1:          private void DoSomething()
   2:          {
   3:              // Do Work
   4:          }
   5:   
   6:          private IEnumerator<ITask> DoSomethingElse()
   7:          {
   8:              // Do work that takes a lot of time 
   9:              // and split up with yield returns
  10:              yield break;
  11:          }
  12:   
  13:          public IEnumerator<ITask> Process()
  14:          {
  15:              yield return Arbiter.FromHandler(DoSomething);
  16:              yield return Arbiter.FromIteratorHandler(DoSomethingElse);
  17:          }

This will however not work and only DoSomething will be executed. The problem is how the execution IEnumerator<ITask> is implemented in CCR. To get it to work you can use a SuccessFailurePort either by passing it in or by returning it. Both approaches are shown in this example:

    1:          private SuccessFailurePort DoSomethingWithPort()
   2:          {
   3:              // Do Work
   4:              SuccessFailurePort port = new SuccessFailurePort();
   5:              port.Post(SuccessResult.Instance);
   6:              return port;
   7:          }
   8:   
   9:          private IEnumerator<ITask> DoSomethingElseWithPort(SuccessFailurePort port)
  10:          {
  11:              // Do work that takes a lot of time 
  12:              // and split up with yield returns
  13:              port.Post(SuccessResult.Instance);
  14:              yield break;
  15:          }
  16:   
  17:          public IEnumerator<ITask> ProcessWithPort()
  18:          {
  19:              yield return DoSomethingWithPort().Choice(CcrServiceBase.EmptyHandler, CcrServiceBase.EmptyHandler);
  20:              SuccessFailurePort port = new SuccessFailurePort();
  21:              SpawnIterator(port, DoSomethingElseWithPort);
  22:              yield return port.Choice(CcrServiceBase.EmptyHandler, CcrServiceBase.EmptyHandler);
  23:          }

In this example no real handler is used for the port so it could be simplified with a more simple port type, but the SuccessFailurePort pattern is pretty nifty so why not use it...