Recipe 7.4 Converting a Synchronous Delegate to an Asynchronous Delegate
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. These delegates should be converted to
asynchronous delegates.
Solution
A typical synchronous delegate is created in the following
manner:
using System;
// The delegate declaration
public delegate void SyncInvoke( );
// The class and method that is invoked through the SyncInvoke delegate
public class TestSyncInvoke
{
public static void Method1( )
{
Console.WriteLine("Invoked Method1");
}
}
The code to use this delegate
is:
public class DelegateUtilities
{
public void TestSimpleSyncDelegate( )
{
SyncInvoke SI = new SyncInvoke(TestSyncInvoke.Method1);
SI( );
}
}
This delegate can be called asynchronously on a thread obtained from
the thread pool by modifying the code as follows:
public class DelegateUtilities
{
public void TestSimpleAsyncDelegate( )
{
AsyncCallback CB = new AsyncCallback(DelegateCallback);
SyncInvoke ASI = new SyncInvoke(TestSyncInvoke.Method1);
IAsyncResult AR = ASI.BeginInvoke(CB, null);
}
// The callback that gets called when Method1 is finished processing
private static void DelegateCallback(IAsyncResult iresult)
{
AsyncResult result = (AsyncResult)iresult;
AsyncInvoke ASI = (AsyncInvoke)result.AsyncDelegate;
int retVal = ASI.EndInvoke(result);
Console.WriteLine("retVal (Callback): " + retVal);
}
}
Of course you might want to also change the
TestSyncInvoke class name to
TestAsyncInvoke and the
SyncInvoke delegate name to
AsyncInvoke 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:
using System;
// The delegate declaration
public delegate int SyncInvoke(string message);
// The class and method that is invoked through the SyncInvoke delegate
public class TestSyncInvoke
{
public static int Method1(string message)
{
Console.WriteLine("Invoked Method1 with message: " + message);
return (1);
}
}
The code to use this delegate
is:
public class DelegateUtilities
{
public void TestComplexSyncDelegate( )
{
SyncInvoke SI = new SyncInvoke(TestSyncInvoke.Method1);
int retVal = SI("Synchronous call");
Console.WriteLine("Sync: " + retVal);
}
}
This synchronous delegate can be converted to an asynchronous
delegate in the following manner:
using System;
using System.Runtime.Remoting.Messaging;
public class DelegateUtilities
{
public void TestCallbackAsyncDelegate( )
{
AsyncCallback CB = new AsyncCallback(DelegateCallback);
SyncInvoke SI = new SyncInvoke(TestSyncInvoke.Method1);
IAsyncResult AR = SI.BeginInvoke("Asynchronous call message", CB, null);
Console.WriteLine("WORKING...");
}
// The callback that gets called when Method1 is finished processing
private static void DelegateCallback(IAsyncResult iresult)
{
AsyncResult result = (AsyncResult)iresult;
AsyncInvoke ASI = (AsyncInvoke)result.AsyncDelegate;
int retVal = ASI.EndInvoke(result);
Console.WriteLine("retVal (Callback): " + retVal);
}
}
Discussion
Converting a delegate from being invoked synchronously to
asynchronously 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.
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.
|