Recipe9.4.Converting Delegate Invocation from Synchronous to Asynchronous


Recipe 9.4. Converting Delegate Invocation from Synchronous to Asynchronous

Problem

You have determined that one or more delegates invoked synchronously within your application are taking a long time to execute. This delay is making the user interface less responsive to the user. The invocation of these delegates should be converted from synchronous to asynchronous mode.

Solution

A typical synchronous delegate type and supporting code that invokes the delegate are shown here:

 public delegate void SyncDelegateTypeSimple(); // The class and method that are invoked through the SyncDelegateTypeSimple delegate public class TestSyncDelegateTypeSimple  {     public static void Method1()     {         Console.WriteLine("Invoked Method1");     } } 

The code to use this delegate is:

 public static void TestSimpleSyncDelegate() {     SyncDelegateTypeSimple sdtsInstance =         new SyncDelegateTypeSimple(TestSyncDelegateTypeSimple.Method1);     sdtsInstance(); } 

This delegate can be called asynchronously on a thread obtained from the thread pool by modifying the code as follows:

 public static void TestSimpleAsyncDelegate() {     AsyncCallback callBack = new AsyncCallback(DelegateSimpleCallback);     SyncDelegateTypeSimple sdtsInstance =          new SyncDelegateTypeSimple(TestSyncDelegateTypeSimple.Method1);     IAsyncResult asyncResult =         sdtsInstance.BeginInvoke(callBack, null);     Console.WriteLine("WORKING…"); } // The callback that gets called when TestSyncDelegateTypeSimple.Method1 // is finished processing private static void DelegateSimpleCallback(IAsyncResult iResult) {     AsyncResult result = (AsyncResult)iResult;     SyncDelegateTypeSimple sdtsInstance =         (SyncDelegateTypeSimple)result.AsyncDelegate;     sdtsInstance.EndInvoke(result);     Console.WriteLine("Simple callback run"); } 

AsyncResult can be found in the System.Runtime.Remoting.Messaging namespace in mscorlib.


Of course you might also want to change the TestSyncDelegateTypeSimple class name to TestAsyncDelegateTypeSimple and the SyncDelegateTypeSimple delegate name to AsyncDelegateTypeSimple just to be consistent with your naming.

The previous example shows how to call a delegate that accepts no parameters and returns void. The next example shows a synchronous delegate that accepts parameters and returns an integer:

 public delegate int SyncDelegateType(string message); public class TestSyncDelegateType {     public static int Method1(string message)     {         Console.WriteLine("Invoked Method1 with message: " + message);         return (1);     } } 

The code to use this delegate is:

 public static void TestComplexSyncDelegate() {     SyncDelegateType sdtInstance =         new SyncDelegateType(TestSyncDelegateType.Method1);     int retVal = sdtInstance("Synchronous call");     Console.WriteLine("Sync: " + retVal); } 

The synchronous invocation of the delegate can be converted to asynchronous invocation in the following manner:

 public static void TestCallbackAsyncDelegate() {     AsyncCallback callBack =         new AsyncCallback(DelegateCallback);     SyncDelegateType sdtInstance =         new SyncDelegateType(TestSyncDelegateType.Method1);     IAsyncResult asyncResult =          sdtInstance.BeginInvoke("Asynchronous call", callBack, null);     Console.WriteLine("WORKING…"); } // The callback that gets called when TestSyncDelegateType.Method1 // is finished processing private static void DelegateCallback(IAsyncResult iResult) {     AsyncResult result = (AsyncResult)iResult;     SyncDelegateType sdtInstance =         (SyncDelegateType)result.AsyncDelegate;     int retVal = sdtInstance.EndInvoke(result);     Console.WriteLine("retVal (Callback): " + retVal); } 

Discussion

Converting the invocation of a delegate from being synchronous to asynchronous is not an overly complicated procedure. You need to add calls to both BeginInvoke and EndInvoke on the delegate that is being called synchronously. A callback method, DelegateCallback, is added, which gets called when the delegate is finished. This callback method then calls the EndInvoke method on the delegate invoked using BeginInvoke.

You must always call EndInvoke when invoking delegates asynchronously, even when the delegate returns void, to ensure proper cleanup of resources in the CLR.


The notification callback method specified in the callback parameter accepts a single parameter of type IAsyncResult. This parameter can be cast to an AsyncResult type and used to set up the call to the EndInvoke method. If you want to handle any exceptions thrown by the asynchronous delegate in the notification callback, wrap the EndInvoke method in a try/catch exception handler.

See Also

See the "Delegate Class" and "Asynchronous Delegates" topics 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