Recipe18.6.Being Notified of the Completion of an Asynchronous Delegate


Recipe 18.6. Being Notified of the Completion of an Asynchronous Delegate

Problem

You need a way of receiving notification from an asynchronously invoked delegate that it has finished. However, it must be more flexible than the notification schemes in the previous two recipes (Recipes 18.4 and 18.5). This scheme must allow your code to continue processing without having to constantly call IsCompleted in a loop or to rely on the WaitOne method. Since the asynchronous delegate will return a value, you must be able to pass this return value back to the invoking thread.

Solution

Use the BeginInvoke method to start the asynchronous delegate, but use the first parameter to pass a callback delegate to the asynchronous delegate, as shown in Example 18-4.

Example 18-4. Getting notification on completion of an anonymous delegate

 using System; using System.Threading; public class AsyncAction2 {     public void CallbackAsyncDelegate( )     {         AsyncCallback callBack = DelegateCallback;         AsyncInvoke method1 = TestAsyncInvoke.Method1;         Console.WriteLine("Calling BeginInvoke on Thread {0}",             Thread.CurrentThread.ManagedThreadId);         IAsyncResult asyncResult = method1.BeginInvoke(callBack, method1);     // No need to poll or use the WaitOne method here, so return to the calling // method.         return;     }     private static void DelegateCallback(IAsyncResult iresult)     {         Console.WriteLine("Getting callback on Thread {0}",             Thread.CurrentThread.ManagedThreadId);         AsyncResult asyncResult = (AsyncResult)iresult;         AsyncInvoke method1 = (AsyncInvoke)asyncResult.AsyncDelegate;         int retVal = method1.EndInvoke(asyncResult);         Console.WriteLine("retVal (Callback): " + retVal);     } } 

This callback delegate will call the DelegateCallback method on the thread the method was invoked on when the asynchronous delegate is finished processing.

The following code defines the AsyncInvoke delegate and the asynchronously invoked static method TestAsyncInvoke.Method1:

 public delegate int AsyncInvoke( ); public class TestAsyncInvoke {     public static int Method1( )     {         Console.WriteLine("Invoked Method1 on Thread {0}",             Thread.CurrentThread.ManagedThreadId );         return (1);     } } 

To run the asynchronous invocation, create an instance of the AsyncAction class and call the CallbackAsyncDelegate method like so:

 AsyncAction aa2 = new AsyncAction(); aa2.CallbackAsyncDelegate(); 

The output for this code is shown next. Note that the thread ID for Method1 is different:

 Calling BeginInvoke on Thread 9 Invoked Method1 on Thread 10 Getting callback on Thread 10 retVal (Callback): 1 

Discussion

The asynchronous delegates in this recipe are created and invoked in the same fashion as the asynchronous delegate in Recipe 18.4. Instead of using the IsCompleted property to determine when the asynchronous delegate is finished processing (or the WaitOne method to block for a specified time while the asynchronous delegate continues processing), this recipe uses a callback to indicate to the calling thread that the asynchronous delegate has finished processing and that its return value, ref parameter values, and out parameter values are available.

Invoking a delegate in this manner is much more flexible and efficient than simply polling the IsCompleted property to determine when a delegate finishes processing. When polling this property in a loop, the polling method cannot return and allow the application to continue processing. A callback is also better than using a WaitOne method, since the WaitOne method will block the calling thread and allow no processing to occur. You can break up the WaitOne method into a limited number of wait cycles as in Recipe 18.5, but this is simply a merging of the polling technique with the WaitOne operation.

The CallbackAsyncDelegate method in this recipe makes use of the first parameter to the BeginInvoke method of the asynchronous delegate to pass in another delegate. This contains a callback method to be called when the asynchronous delegate finishes processing. After calling BeginInvoke, this method can now return and the application can continue processing; it does not have to wait in a polling loop or be blocked while the asynchronous delegate is running.

The AsyncInvoke delegate that is passed into the first parameter of the BeginInvoke method is defined as follows:

 public delegate void AsyncCallback(IAsyncResult ar) 

When this delegate is created, as shown here, the callback method passed in, DelegateCallback, will be called as soon as the asynchronous delegate completes:

 AsyncCallback callBack = new AsyncCallback(DelegateCallback); 

DelegateCallback will not run on the same thread as BeginInvoke but rather on a Thread from the ThreadPool. This callback method accepts a parameter of type IAsyncResult. You can cast this parameter to an AsyncResult object within the method and use it to obtain information about the completed asynchronous delegate, such as its return value, any ref parameter values, and any out parameter values. If the delegate instance that was used to call BeginInvoke is still in scope, you can just pass the IAsyncResult to the EndInvoke method. In addition, this object can obtain any state information passed into the second parameter of the BeginInvoke method. This state information can be any object type.

The DelegateCallback method casts the IAsyncResult parameter to an AsyncResult object and obtains the asynchronous delegate that was originally called. The EndInvoke method of this asynchronous delegate is called to process any return value, ref parameters, or out parameters. If any state object was passed in to the BeginInvoke method's second parameter, it can be obtained here through the following line of code:

 object state = asyncResult.AsyncState; 

See Also

See the "AsyncCallback Delegate" topic in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net