Tuesday, July 7, 2009

Fast Asynchronous Delegates in .NET


This article describes how to implement a delegate which performs much better during BeginInvoke/EndInvoke operations, than the delegates with default implementation of BeginInvoke/EndInvoke injected by CLR. The idea is rather simple, no cheats with IL and function pointers.


In .NET, there is 3 ways to execute an operation or a task asynchronously. The first approach consists in using of System.Threading.ThreadPool, which suits the best in most cases. The second approach is Thread.Start, which fits better than ThreadPool, for the cases of long-running operations. And the last one is APM pattern (pair of methods BeginSomething/EndSomething) provided by all delegates and some major classes, like Stream, WebRequest, etc. APM pattern suits the best when you need to retrieve a result of an asynchronous operation.

Let's consider more closely delegates in .NET. Each delegate in .NET is decorated by C# compiler with such methods as BeginInvoke and EndInvoke. These methods at some degree are abstract - C# compiler does not provide any implementation at compile time. Implementation is injected later by CLR. BeginInvoke/EndInvoke seems to be the perfect choice when we need to retrieve a result or an absence of a result (which is called an exception) of an asynchronous operation. But the "perfect" word here is valid only in the scope of logical design. When it comes to performance, be careful: "Avoid using BeginInvoke/EndInvoke methods as much as possible. The reason is both methods internally use remoting infrastructure." - this statement I've recently encountered in one of the Microsoft's books (I've rephrased it a little bit). Basically, I was interested in the fact, how much slower than ThreadPool, for instance, are those two methods. Therefore I've implemented my own versions of BeginInvoke/EndInvoke.

Using the Code

The usage of my APM pattern implementation is exactly the same, as the default one. Here is an example:

See full detail: http://www.codeproject.com/KB/dotnet/fastasyncdelegates.aspx