locked
Using the _mainPort for internal messages? RRS feed

  • Question

  • Hello,

     

    Inpired by the Robotics tutorial 6 I built a service to communiate with an 8 bit microcontroller robot.  The tutorial makes it clear that data received from the robot should be passed in a message to an exclusive lock handler before altering the state.  The tutorial uses a new internal pot to do this.  Instead, I just used the _mainPort, and added a new message type that contains the updates from the Robot, to the operations port class.

     

    The advantage of using the existing mainport was simplicity and efficiency.   I just needed to add a new mesage type, and an exclusive lock handler to deal with it, and it all works beautifully.  From a DSS good practice point of view, should I be posting internally to the _mainPort like this, or is it really better to set up a new internal port with an exclusive lock handler (and if so how?  - tutorial 6 didn't show it.) 

     

    Many thanks in advance for your comments!

     

    Best regards,

     

    Andrew

    Sunday, April 1, 2007 1:01 PM

Answers

  •  

    Regarding setting up an exclusive 'lock', I believe to can make the private port handler exclusive through the use of an interleave.  Since an interleave is already set up for you (by DssServiceBase.Start(), you'll need to perform the actions Start() performs in your start implementation)

     

    Before:

    Code Snippet

    class MyService

    {

      [ServiceHandler]

      IEnumerator MyHandler1(Msg1 m) { ... }

     

      void Start() {

        base.Start();

      }

    }

     

    After:

    Code Snippet

    class MyService

    {

      [ServiceHandler]

      IEnumerator<ITask> MyHandler1(Msg1 m) { ... }

     

      // EXCLUSIVE handler on _privatePort

      IEnumerator<ITask> MyPrivateHandler(PrivateMessage m) { ... }

     

      void Start()

      { 

        Interleave mainInterleave;

        // base.Start implementation:

        {

          // This gets the interleave that contains MyHandler1

          mainInterleave = ActivateDsspOperationHandlers();

     

          DirectoryInsert();

     

          LogInfo(LogGroups.Console, "Service uri: ");

        }

     

        // extend the auto-generated interleave to include our private port

        mainInterleave.CombineWith(

          Arbiter.Interleave(

            new TeardownReceiverGroup(),

            new ExclusiveReceiverGroup(

              Arbiter.ReceiveWithIterator( true, _privatePort, MyPrivateHandler))

              /* other exclusive private port handlers can go here */

            ),

            new ConcurentReceiverGroup(   /* concurrent private port handlers can go here */ )

          )

        );

      }

    }

     

     

    Adding to your main port is always an option.  If you do that, you can use the declarative syntax (ie, [ServiceContract] instead of manually calling Arbiter.Recieve), but the private message now becomes part of your public interface -- any other service will be able to send that message to your main port.  

     

     

    [UPDATE] In original post, I used Receive instead of ReceiveWithIterator.  This post has been corrected.  The following thread discusses the difference between the two:

     

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1420437&SiteID=1

     

     

    #aaron

     

     

    Monday, April 2, 2007 4:23 PM

All replies

  •  

    Regarding setting up an exclusive 'lock', I believe to can make the private port handler exclusive through the use of an interleave.  Since an interleave is already set up for you (by DssServiceBase.Start(), you'll need to perform the actions Start() performs in your start implementation)

     

    Before:

    Code Snippet

    class MyService

    {

      [ServiceHandler]

      IEnumerator MyHandler1(Msg1 m) { ... }

     

      void Start() {

        base.Start();

      }

    }

     

    After:

    Code Snippet

    class MyService

    {

      [ServiceHandler]

      IEnumerator<ITask> MyHandler1(Msg1 m) { ... }

     

      // EXCLUSIVE handler on _privatePort

      IEnumerator<ITask> MyPrivateHandler(PrivateMessage m) { ... }

     

      void Start()

      { 

        Interleave mainInterleave;

        // base.Start implementation:

        {

          // This gets the interleave that contains MyHandler1

          mainInterleave = ActivateDsspOperationHandlers();

     

          DirectoryInsert();

     

          LogInfo(LogGroups.Console, "Service uri: ");

        }

     

        // extend the auto-generated interleave to include our private port

        mainInterleave.CombineWith(

          Arbiter.Interleave(

            new TeardownReceiverGroup(),

            new ExclusiveReceiverGroup(

              Arbiter.ReceiveWithIterator( true, _privatePort, MyPrivateHandler))

              /* other exclusive private port handlers can go here */

            ),

            new ConcurentReceiverGroup(   /* concurrent private port handlers can go here */ )

          )

        );

      }

    }

     

     

    Adding to your main port is always an option.  If you do that, you can use the declarative syntax (ie, [ServiceContract] instead of manually calling Arbiter.Recieve), but the private message now becomes part of your public interface -- any other service will be able to send that message to your main port.  

     

     

    [UPDATE] In original post, I used Receive instead of ReceiveWithIterator.  This post has been corrected.  The following thread discusses the difference between the two:

     

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1420437&SiteID=1

     

     

    #aaron

     

     

    Monday, April 2, 2007 4:23 PM
  •  

    It may be more reliable to call base.Start(), and use the "this.MainPortInterleave" property to get access to the main interleave:

     

    Code Snippet

      void Start()

      { 

        base.Start();

     

        // extend the auto-generated interleave to include our private port

        this.MainInterleave.CombineWith(

          Arbiter.Interleave(

            new TeardownReceiverGroup(),

            new ExclusiveReceiverGroup(

              Arbiter.ReceiveWithIterator( true, _privatePort, MyPrivateHandler))

              /* other exclusive private port handlers can go here */

            ),

            new ConcurentReceiverGroup(   /* concurrent private port handlers can go here */ )

          )

        );

      }

     

    #aaron

     

     

    Saturday, April 7, 2007 4:14 AM
  • Neat, I didn't know about this.MainInterleave.  That is much cleaner.  You say it is more reliable... in what way?

    Saturday, April 7, 2007 4:08 PM
  • er...may i know how u use the main port for the communication?i'm in the middle find the way to write a simple service just for serial port, but seem like it also need a internal port, and after refering for the examples come with MSRS, i still cannot find the way, could you please share your method with me?i mean just a simple c# code without many of .cs file in a project,,,tq....
    Monday, October 20, 2008 6:51 AM
  • Here are the message handlers I added:

     

    #region DSS _mainPort message handlers

    [ServiceHandler(ServiceHandlerBehavior.Concurrent)]

    public virtual IEnumerator<ITask> GetHandler(Get get)

    {

    get.ResponsePort.Post(_state);

    yield break;

    }

    [ServiceHandler(ServiceHandlerBehavior.Concurrent)]

    public IEnumerator<ITask> HttpGetHandler(HttpGet httpGet)

    {

    httpGet.ResponsePort.Post(new HttpResponseType(_state));

    yield break;

    }

     

     

    [ServiceHandler(ServiceHandlerBehavior.Exclusive)]

    public IEnumerator<ITask> GriffinUpdateHandler(GriffinUpdate _GriffinUpdate)

    {

    try

    {

    // Some code

    }

    catch (Exception e)

    {

     

    }

    yield break;

    }

     

    Monday, October 20, 2008 8:25 AM