How to use an AsyncResult?

I have a much longer article in mind for this and will be publishing it out soon. But to quickly answer this let us use an implementation from the framework itself using a delegate. Please note, this is for a usage pattern sample only since all that a delegate does is put the work on the CLR’s thread pool which means more latency for non-blocking work.Lets create a driver for our async operation which will define our little piece of work. Here we just return a string. [more]

class AyncOperation{    // Your delegate to simulate an AsyncResult implementation    static Func operation = () => "Hello operation.";    internal static IAsyncResult BeginOperation(AsyncCallback callback, object state)...    internal static string EndOperation(IAsyncResult result)...}

This is what is expected on the 2 paths that the code can complete on.

  • Synchronous Path
    • IAsyncResult result = BeginOperation()
    • Is Result.CompletedSynchronously  == true
      • Yes
        • Handle the completion like calling end etc.
        • Handle exceptions.
      • No
        • Do nothing and return
  • Callback
    • IS Result.CompletedSynchronously  == true
      • Yes
        • return as the sync path will take care of the rest
      • NO
        • Handle the completion
        • Handle exception if any

So here is the end to end implementation.

namespace Microsoft.Samples.SimpleDelegateAsyncResult{    using System;    using System.Threading;    class Program    {        static AsyncCallback onCallback = new AsyncCallback(Callback);        ManualResetEvent waitHanlde = new ManualResetEvent(false);        static void Main(string[] args)        {            Program state = new Program();            try            {                IAsyncResult result = AyncOperation.BeginOperation(onCallback, state);                if (result.CompletedSynchronously)                {                    state.HandleCompletion(result);                }            }            catch (Exception exception)            {                Console.WriteLine(" Exception : " + exception.Message);                // Do the same exception handling here.                state.waitHanlde.Set();            }            state.waitHanlde.WaitOne();            state.waitHanlde.Close();            Console.WriteLine("Completed");        }        static void Callback(IAsyncResult result)        {            if (result.CompletedSynchronously)                return;            Program thisPtr = result.AsyncState as Program;            Exception completionException = null;            try            {                thisPtr.HandleCompletion(result);            }            catch (Exception ex)            {                // Don't throw as you cannot bubble up exceptions on  a callback thread                completionException = ex;            }            finally            {                if (completionException != null)                {                    // you need to handle exception here as well                    Console.WriteLine("Callback Exception : " + completionException.Message);                }                //release the main thread;                thisPtr.waitHanlde.Set();            }        }        void HandleCompletion(IAsyncResult result)        {            Console.WriteLine(AyncOperation.EndOperation(result));             //throw new InvalidOperationException("test exception");            Thread.Sleep(100);        }    }    class AyncOperation    {        // Your delegate to simulate an AsyncResult implementaion        static Func operation = () => "Hello operation.";        internal static IAsyncResult BeginOperation(AsyncCallback callback, object state)        {            return operation.BeginInvoke(callback, state);        }        internal static string EndOperation(IAsyncResult result)        {            return operation.EndInvoke(result);        }    }}