Summary: Some common patterns of messaging inside DSSP services through CCR arbiters and ports

Through proxies:

using srv1 = MyCompany.Robotics.Services.Service1.proxy;
...

		    srv1.Service1Operations port = new srv1.Service1Operations();
	

		    Activate(Arbiter.Choice(port.Get(),
		        [delegate(srv1.GetResponseType] response)
		        {
		            ...
		        },
		        delegate(Fault fault)
		        {
		            ...
		            [LogError(fault);]
		        }
		    );
	


Services inside an assembly (no proxy):

using srv1 = MyCompany.Robotics.Services.Service1;
...

		    srv1.Service1Operations port = new srv1.Service1Operations();
	

		    srv1.Get get = new srv1.Get();
	

		    port.Post(get);
		    [Activate(Arbiter.Choice(get.ResponsePort,]
		        [delegate(srv1.GetResponseType] response)
		        {
		            ...
		        },
		        delegate(Fault fault)
		        {
		            ...
		            [LogError(fault);]
		        }
		    );
	


In an enumerator (proxy):
using srv1 = MyCompany.Robotics.Services.Service1.proxy;
...

srv1.Service1Operations _port = new srv1.Service1Operations();

public IEnumerator<ITask> Handler1(srv1.Itemx itemx)
{
		    yield return Arbiter.Choice(_port.Get(),
		        [delegate(srv1.GetResponseType] response)
		        {
		            ...
		        },
		        delegate(Fault fault)
		        {
		            ...
		            [LogError(fault);]
		        }
		    );
	
}


In an enumerator (no proxy):
using srv1 = MyCompany.Robotics.Services.Service1;
...

srv1.Service1Operations _port = new srv1.Service1Operations();

public IEnumerator<ITask> Handler1(srv1.Itemx itemx)
{
		    srv1.Get get = new srv1.Get();
		    _port.Post(get);
		    yield return [Arbiter.Choice(get.ResponsePort,]
		        [delegate(srv1.GetResponseType] response)
		        {
		            ...
		        },
		        delegate(Fault fault)
		        {
		            ...
		            [LogError(fault);]
		        }
		    );
	
}


Note: When yield returning, you should not activate arbiter as the caller will take care of activating an arbiter on the yield returned task item. You can define the port object in the scope of the method and it is not garbage collected as long as there are task items queued in the port. So it is very important to always activate the port with an arbiter or the port will leak. Functionally it does not matter if you activate first or post to the port first. A task item would not be processed until its port is activated with an Arbiter which reads the task item from the port and queues it in a DispatcherQueue to be processed. If the activation is persistent, then you can Activate first with persistent parameter set to true, and then post multiple task items to the activated port.

If deriving from the DsspServiceBase there is an Activate helper method which is derived from CcrServiceBase.
@public void Activate<T>(params T[] tasks) where T: ITask@
If using the CCR out of a service, then you have to use Microsoft.Ccr.Core.Arbiter.Activate (in Ccr.Core.dll) instead.



For more information on CCR arbiters see:
Concurrency and Coordination Runtime, MSDN article
http://msdn.microsoft.com/msdnmag/issues/06/09/concurrentaffairs/default.aspx

An Asynchronous Messaging Library for C# 2.0
http://channel9.msdn.com/wiki/default.aspx/Channel9.ConcurrencyRuntime
Microsoft Communities