none
Where can I learn to wrap my mind around Choice, Arbiter, yield, etc.? RRS feed

  • Question

  • I'm fairly new to C#, and I can't seem to wrap my brain around the Choice object.  It is barely more than mentioned in the one of my hardcopy books that mentions it, but I see it straightfowardly used and presented with little explanation in many of the online tutorials I've worked with or looked at.    For example, if you look at the MSDN DSS tutorials, they all use it, for example here from DSS Tutotial 6:  

     

     

                // Add the handlers for notifications from ServiceTutorial4.
    
                // This is necessary because these handlers do not handle
    
                // operations in this service, so you cannot mark them with
    
                // the ServiceHandler attribute.
    
                MainPortInterleave.CombineWith(
    
                    new Interleave(
    
                        new TeardownReceiverGroup(),
    
                        new ExclusiveReceiverGroup(),
    
                        new ConcurrentReceiverGroup(
    
                            Arbiter.Receive<rst4.IncrementTick>(true, _clockNotify, NotifyTickHandler),
    
                            Arbiter.Receive<rst4.Replace>(true, _clockNotify, NotifyReplaceHandler)
    
                        ))
    
                );
    
    
    
    

    Naturally, I realize there's a LOT of new stuff I'm taking on here, but this code really doesn't make sense to me.   I can get through the tutorial but it has little value if I'm just typing or pasting stuff without knowing what it means.   Are delegates being invoked here?   I do understand the basic principle of delegates, but am not yet comfortable with them as I would be with, let's say, a "for" loop.  So perhaps I'm missing it in a larger and unfamiliar context.  

    To take another example, I understand "yield" is a late-binding tool so to speak, that executes and delivers a query result at the time of execution.   But what the heck is "yield return", as in this example, also from DSS Tutorial 6?

     

            private IEnumerator<ITask> OnStartup()
    
            {
    
                rst4.Get get;
    
                <strong><em>yield return _clockPort.Get(GetRequestType.Instance, out get);</em></strong>
    
                rst4.ServiceTutorial4State state = get.ResponsePort;
    
                if (state == null)
    
    //lots of code in the if block
    
    
    
                }
    
                rst4.Subscribe subscribe;
    
                yield return _clockPort.Subscribe(_clockNotify, out subscribe);
    
                Fault fault = subscribe.ResponsePort;
    
                if (fault != null)
    
                {
    
                    LogError("Unable to subscribe to ServiceTutorial4", fault);
    
                }        
    
            }
    
    Doesn't the yield return force an exit from the function at that point?
    Are there any good tutorials online that give a detailed, top-down introduction to this area, the way you can find numerous example of delegates, Windows Forms, and so on?
    <br/><br/><br/>

    • Edited by Pithecanthropus Tuesday, June 30, 2009 7:53 AM
    • Moved by Harry Zhu Thursday, July 2, 2009 1:24 AM (From:Visual C# General)
    Tuesday, June 30, 2009 7:51 AM

Answers

  • You are actually asking several questions in one.

    CCR works with messages that are sent to ports. Choice is a type of receiver that allows you to wait for a message to arrive on one of several ports, although in practise there are usually only two ports. In particular, in DSS Services, you often wait on a PortSet which consists of a port to receive the response to a request and a port to receive a Fault (which indicates that the request failed), i.e. two different types messages might be received. This is like a logical OR on two ports. (The logical AND operation is called a Join, but let's not go there for now).

    The MainPortInterleave is completely unrelated to Choice. In DSS Services, this "interleave" is used to guarantee exclusive access to the service state by handlers that have to write to (update) the state. You can have many Concurrent readers, but only one Exclusive writer, running at the same time. Notice that there are Concurrent and Exclusive receiver groups in the interleave. (Ignore Teardown which is only for handlers that must run when the service is dropped and is often not used).

    Lastly, Iterators are used to execute handlers so that threads are not blocked when the handler needs to wait for a message. An IEnumerator is a mechanism in C# to "enumerate" something. For example, if you have an array, you can "enumerate" the elements of the array so that you can process them in order one at a time. In DSS, we use this as a way to execute a series of "tasks" one after another (which is why it is IEnumerator<ITask>). The yield return indicates to the compiler where one task ends and a new one begins. The tasks are created for you. So what looks like a straight sequential piece of code is actually a set of tasks that wait for a message after each step.

    (As an aside, you can use yield break to terminate the handler early if you want to. This is like the return from a normal function. Don't ask me why the C# people chose to call it yield break instead of yield return. The "return" in yield return actually means "return here to continue executing later" and the "break" in yield break is sort of like the break inside a for loop or a switch.)

    This way of writing the code is much cleaner than creating a set of callback routines, which you have to do in other languages, that are executed one after another and "daisy-chained" together.

    Notice that the yield return in your example waits on a response to a Subscribe message. When the response arrives, it tries to cast the result to a Fault. If the response message was not a Fault, i.e. the Subscribe was successful, then it just continues. While the handler is waiting for the Subscribe to be processed, IT DOES NOT BLOCK A THREAD. The yield return allows CCR to re-use the thread for something else. When the code resumes after the yield return, it might even be executing on a different thread, but you probably did not need to know that :-)

    I don't know which book you have, but I think this is explained in our book Professional Robotics Developer Studio.

    Trevor
    Friday, July 3, 2009 2:27 AM

All replies

  • Thanks to Harry Zhu for moving this to the correct forum. 

    Another way I could state my question is this:  when I read the DSS Tutorials and work through them, I can understand what is supposed to be happening at most places in the presentation, but I don't quite understand how this is being accomplished.   That is, I can't parse the code so as to be able to map it to the steps of work being done.
    Thursday, July 2, 2009 2:37 PM
  • You are actually asking several questions in one.

    CCR works with messages that are sent to ports. Choice is a type of receiver that allows you to wait for a message to arrive on one of several ports, although in practise there are usually only two ports. In particular, in DSS Services, you often wait on a PortSet which consists of a port to receive the response to a request and a port to receive a Fault (which indicates that the request failed), i.e. two different types messages might be received. This is like a logical OR on two ports. (The logical AND operation is called a Join, but let's not go there for now).

    The MainPortInterleave is completely unrelated to Choice. In DSS Services, this "interleave" is used to guarantee exclusive access to the service state by handlers that have to write to (update) the state. You can have many Concurrent readers, but only one Exclusive writer, running at the same time. Notice that there are Concurrent and Exclusive receiver groups in the interleave. (Ignore Teardown which is only for handlers that must run when the service is dropped and is often not used).

    Lastly, Iterators are used to execute handlers so that threads are not blocked when the handler needs to wait for a message. An IEnumerator is a mechanism in C# to "enumerate" something. For example, if you have an array, you can "enumerate" the elements of the array so that you can process them in order one at a time. In DSS, we use this as a way to execute a series of "tasks" one after another (which is why it is IEnumerator<ITask>). The yield return indicates to the compiler where one task ends and a new one begins. The tasks are created for you. So what looks like a straight sequential piece of code is actually a set of tasks that wait for a message after each step.

    (As an aside, you can use yield break to terminate the handler early if you want to. This is like the return from a normal function. Don't ask me why the C# people chose to call it yield break instead of yield return. The "return" in yield return actually means "return here to continue executing later" and the "break" in yield break is sort of like the break inside a for loop or a switch.)

    This way of writing the code is much cleaner than creating a set of callback routines, which you have to do in other languages, that are executed one after another and "daisy-chained" together.

    Notice that the yield return in your example waits on a response to a Subscribe message. When the response arrives, it tries to cast the result to a Fault. If the response message was not a Fault, i.e. the Subscribe was successful, then it just continues. While the handler is waiting for the Subscribe to be processed, IT DOES NOT BLOCK A THREAD. The yield return allows CCR to re-use the thread for something else. When the code resumes after the yield return, it might even be executing on a different thread, but you probably did not need to know that :-)

    I don't know which book you have, but I think this is explained in our book Professional Robotics Developer Studio.

    Trevor
    Friday, July 3, 2009 2:27 AM
  • The best way to learn C# and CCR is to use it.
    I know as I started learned both only earlier this year.

    i've compiled a bunch of links and resources here

    the CCR introduces quite a few new concepts, which makes it tricky to learn while you are 'concurrently' learning a new programming language as well.

    I recommend getting a hold of the free chapter from WROX on the Robotics Developer Studio.  The site is currently unavailable, but i believe it should be up again soonish.

    Learning one small step at a time
    Thursday, July 23, 2009 1:11 PM
  • By the way, I haven't even tried to get my head around the DSS yet!
    Thankfully the CCR can be used sepperatly in projects.
    Learning one small step at a time
    Thursday, July 23, 2009 1:12 PM