The .NET Framework enables you to call any method asynchronously. Delegates enable you to call a synchronous method in an asynchronous manner. When you call a delegate synchronously, the Invoke method calls the target method directly on the current thread. If the BeginInvoke method is called, the common language runtime (CLR) queues the request and returns immediately to the caller. The target method is called asynchronously on a thread from the thread pool. The original thread, which submitted the request, is free to continue executing in parallel with the target method. If a callback method has been specified in the call to the BeginInvoke method, the callback method is called when the target method ends. In the callback method, the EndInvoke method obtains the return value and any input/output or output-only parameters. If no callback method is specified when calling BeginInvoke, EndInvoke can be called from the thread that called BeginInvoke.
There are several patterns to call a synchronous method asynchronously as shown below.
1- BeginInvoke and EndInvoke
2- WaitHandle
3- Polling
4- Callback
BeginInvoke and EndInvoke Pattern
As you see that first message written in console is worked in main thread (ThreadID is 1), But, DoWork() method is called asynchronously, so that, second message is worked on different thread (ThreadID is 3).
DoWork() method returns int value and without parameters, so that, BeginInvoke method shows two parameters(callback, @object) as shown in Figure-2
Notice that EndInvoke() method takes asyncResult variable returned by BeginInvoke() method and it also returns int value because of Func delegate in Figure-3.
If method has some parameters, first parameters of BeginInvoke() method will be same as shown in Figure-5.
Notice that DoWork() method is not used directly, it is encapsulated with a delegate. I used
Func<int, int, int>
delegate which is signature of DoWork() method in this code.
Let's examine declaration of DoWork() method below. you see that there are two int parameters and returns int type.
int DoWork(int num1, int num2) is equals to Func<int, int, int>
Let's use our delegate MethodCaller
Let's see how to use anonymous delegate asynchronously.
I will always use anonymous delegates in examples from now on. Below code will also show using delegate with lambda notation.
WaitHandle Pattern
You can perform additional processing before or after the asynchronous call complete using WaitHandle.
Polling Pattern
Use Polling for completion allows the calling thread to continue executing while the asynchronous call executes on a ThreadPool thread.