Exploring Asynchronous Design Patterns
One programming pattern that could be made easier for the
developer is implementing the IAsyncResult
asynchronous programming pattern. Writing code so it doesn’t block threads is
difficult to do. It is even more
difficult using this pattern because there are multiple different ways for a
programmer call an operation implementing the pattern.
Once you do have a basic implementation, though, it is a
tedious and repetitive task to create asynchronous operations on your classes. This means that with asynchronous operations there
is an opportunity that the right tools could help make development easier. Before we can create the tools, we will need a
basic pattern and supporting code.
You can find documentation on asynchronous programming in
MSDN, however, as time goes by the documentation gets more heavily weighted
toward the event based pattern. It is increasingly hard to find documentation
on how to use or implement the older pattern.
The MSDN page for APM is here though.
The other interesting thing is that even the event based pattern may be going
away now as well, in favor of built in language support in C# 5.0 for the Tasks
library (Hint: Search for “AsyncCTP”). This
is a great topic for another post. In the meantime, if you need to support
asynchronous operations using a framework 3.5 and earlier, it may be good to
know one of the previous patterns.
Asynchronous
Programming Model Use
Because the documentation is getting scarce, I feel
obligated to give a brief overview of how to use the programming model.
Typically, there are two matching methods on a class with signatures similar to
those shown below:
IAsyncResult
BeginConnect(string host, int port, AsyncCallback userCallback, object state);
void
EndConnect(IAsyncResult result);
The
application would typically use the above example methods (from the Socket
class) as follows:
IAsyncResult
result = m_socket.BeginConnect(
m_host,
m_port,
this.ConnectCompleted,
null /*state*/);
private void
ConnectCompleted(IAsyncResult result)
{
try
{
m_socket.EndConnect(result);
// Additional code here
}
catch (SocketException exception)
{
// TODO: Handle exception
}
}
Exceptions
and data (if any) are reported in the EndXXX method when the operation
completes. When implementing this pattern, it is necessary to return an object
that implements the IAsyncResult interface from the Begin method and will be
passed to the callback when completed. There are
ways of blocking threads and waiting synchronously on the operation, but if
your goal is to not block threads then these are hopefully not of interest to
you.
You may still
able to find more information on the internet if necessary to understand how
this pattern or even the event based pattern is used.
Summary
Asynchronous
programming is difficult, and implementing asynchronous operations to prevent
threads from blocking is even more difficult. Once you have done it a few
times, it becomes very tedious to do.
Many people have given their perspective and coding patterns to
accomplish this task already. Like everyone else, I will quickly give my own
spin on it in the next post, so we can get past that and onto how to make
things easier.
Series