I have been extremely busy on a client site recently. One of the challenges was a class design that supported asynchronous operations.
I soon found out that utilizing the asynchronous functionality built into delegates produced poor performance. This is due to the overhead of the remoting infrastructure that delegates so beautifully supports, so ThreadPool.QueueUserWorkItem was favored here.
I needed some boilerplate code for the basic of this Async Pattern so implementing the IAsyncResult interface is the key to creating a successfully class design supporting asynchronous operations.
My basic implementation goes like this:
public class AsyncResult : IAsyncResult { private object state; internal bool complete = false; internal AutoResetEvent are; internal AsyncCallback callback; internal AsyncResult(AsyncCallback callback, object state) { this.callback = callback; this.state = state; this.are = new AutoResetEvent(false); } public virtual object AsyncState { get { return state; } set { state=value;} } public bool IsCompleted { get {return complete; }} public WaitHandle AsyncWaitHandle {get {return are; }} public bool CompletedSynchronously {get {return false; }} }
pretty strait forward, now lets see how we can utilize this implementation in class design with asynchronous support.
public class FibonacciEx { private static void Fibonacci(object data) { AsyncResult m = (AsyncResult)data; int n = (i nt)m.AsyncState; int previous = -1; int result = 1; for (int i = 0; i <= n; ++i) { int sum = result + previous; previous = result; result = sum; } m.AsyncState = result; m.complete = true; m.are.Set(); }
public IAsyncResult BeginFib(AsyncCallback callback, object state) { AsyncResult ar = new AsyncResult(callback, state); ThreadPool.QueueUserWorkItem(new WaitCallback(Fibonacci), ar); return ar; }
public int EndFib(IAsyncResult ar) { AsyncResult reqState = (AsyncResult)ar; //are we done if (!reqState.IsCompleted) reqState.AsyncWaitHandle.WaitOne(); //invoke our callback function if(reqState.callback!=null) reqState.callback(reqState); //in this class design we return the result also. return (int)reqState.AsyncState; } }
and the usage of this simpel class could be like this:
class AsyncSample { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { int seq1=0; int seq2=0; float goldenRatio = 0; FibonacciEx fib = new FibonacciEx();
AsyncCallback ac = new AsyncCallback(FibResult); IAsyncResult res = fib.BeginFib(ac, 9); // //do some other important stuff // seq1 = fib.EndFib(res); ac = new AsyncCallback(FibResult); res = fib.BeginFib(ac, 10); // //do some other important stuff // seq2 = fib.EndFib(res);
//calculate the golden ratio, the phi, the magic number. goldenRatio = (float)seq2/seq1;
Console.WriteLine("Magic number: " + goldenRatio.ToString()); Console.ReadLine(); } public static void FibResult(IAsyncResult ar) { Console.WriteLine(ar.AsyncState.ToString()); } }
use the AsyncResult boilerplate for your furture class design if you must support the Async Pattern.
1:44:26 PM
|