Asynchronous methods in C# using generics
September 24, 2010 Leave a comment
Asynchronous methods provide a means to execute long running operations in parallel. One strategy for implementing these is to define generic methods to handle the asynchronous actions and pass the methods to be called asynchronously as parameters. A simple example follows.
The generic support methods
A class is created with static methods to support start and completion of asynchronous methods. The support methods for a single parameter with return type are shown. Other methods can be added to handle other delegate signature requirements.
// Parameter and return type async method helper public static IAsyncResult BeginAsync<T1, TResult>(Func<T1, TResult> method, T1 parameter) { var methodCopy = method; if (methodCopy == null) throw new ArgumentNullException(); // Start the asynchronous operation // No callback or state object return methodCopy.BeginInvoke(parameter, null, null); } // Parameter and return type async method helper - async done public static TResult EndAsync<T1, TResult>(IAsyncResult aResult) { Func<T1, TResult> method = (Func<T1, TResult>) ((AsyncResult) aResult).AsyncDelegate; // Retrieve the result return method.EndInvoke(aResult); }
Asynchronous running
With these methods in place it becomes a simple process to use the asynchronous operations in code. Each operation calls the appropriate generic method to invoke the function, and a generic method to retrieve the result. A blocking strategy is shown here (so not applicable for use in a UI thread) but the example can easily be modified to use callbacks on completion.
private int LongComputation(String data) { // Some long operation Thread.Sleep(10000); return data.Length; } private int MultiComputation() { IAsyncResult aRes1 = AsyncMethods.BeginAsync<String, int>(LongComputation, "Visions"); IAsyncResult aRes2 = AsyncMethods.BeginAsync<String, int>(LongComputation, "of"); IAsyncResult aRes3 = AsyncMethods.BeginAsync<String, int>(LongComputation, "Software"); // Blocks for async call completion - not for use on UI thread int result = AsyncMethods.EndAsync<String, int>(aRes1); result += AsyncMethods.EndAsync<String, int>(aRes2); result += AsyncMethods.EndAsync<String, int>(aRes3); return result; }