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);
        }
    }
}