Building Responsive .NET Applications with Microsoft Concurrency and Coordination Runtime (CCR)
AsyncCallBackFactory
I borrowed the idea behind this class from the "Concurrent Affairs Concurrency and Control Runtime" article You can access the article in the Resources section at the end of the article. AsyncCallBackFactory appears below.
sealed class AsyncCallbackFactory { //Wires the Ports to the Callback function so when async completes //the results are posted to a port. public static PingCompletedEventHandler Create(Port<PINGCOMPLETEDEVENTARGS> portResult, Port<PINGEXCEPTIONINFO> portException) { AsyncCallbackMethodAdapter builder = new AsyncCallbackMethodAdapter(portResult, portException); return builder.CompletedCallBack; } //This class wires the ports to the callback method private sealed class AsyncCallbackMethodAdapter { private Port<PINGCOMPLETEDEVENTARGS> _portResult; private Port<PINGEXCEPTIONINFO> _portException; internal AsyncCallbackMethodAdapter(Port<PINGCOMPLETEDEVENTARGS> portResult, Port<PINGEXCEPTIONINFO> portException) { _portResult = portResult; _portException = portException; } // Called to process result of completion internal void CompletedCallBack(object sender, PingCompletedEventArgs e) { if (e.Error == null) { // Post success item to success Port _portResult.Post(e); } else { PingExceptionInfo info = new PingExceptionInfo(); info.Ex = e.Error; info.resource = e.UserState.ToString(); //Send the error object _portException.Post(info); } } } }
As I stated earlier, the class returns a function
matching the PingCompletedEventFunction
delegate. Essentially, the Create function returns a
reference to the CompletedCallBack
function
inside a private class called
AsyncCallBackMethodAdapter
which is known only
to the AsyncCallBackFactory
class.
This may be an odd way of implementing this, but consider
other APM operations you may be performing using other
classes in the .NET Framework. Most APM "End" functions
result in success or an Exception. It may be useful to
handle them all in a similar way and to have an overloaded
static Create
function for each APM class'
operation. If an assignment is repeated why not perform the
process once and be done with it? Also using an intermediate
class allows for some common processing before posting to
the Ports.
Further Investigation
There is quite a bit more to CCR. Here are examples of other CCR features not demonstrated in the example code.
Policies allow a DispatcherQueue
to throttle
message processing. Policies are useful when only a handful
of the most recent messages make sense to process and older
messages should be ignored. Timers are another useful CCR
feature. Utilize timers when a queue must receive a message
before an elapsed span of time and perform an alternative
action if the time expires first. Joins
allow a
developer to chain response dependencies together. For
example, a Join
allows a developer to configure
a response when a particular number of Ports are activated.
In a future article, I'll demonstrate how I applied CCR to a
MSMQ solution.
Conclusion
Concurrency and Coordination Runtime (CCR) originated in Robotics Studio, but can be leveraged outside of Robotics. In fact, CCR is a great platform for the .NET Framework Asynchronous Programming Model (APM). In this article I demonstrated how CCR can work with the .Net Ping class' APM functions.
Sources
CCR and DSS Home Page
Concurrent Affairs Concurrency and Control Runtime
PDC 2008 presentation: The Concurrency and Coordination Runtime and Decentralized Software Services Toolkit
CCR Programming - Jeffrey Richter and George Chrysanthakopoulos
Page 4 of 4
This article was originally published on July 23, 2009