Async Method with Callback

.Async Method with Callback


Async Method with Callback Program Output

.Async Method with Callback

"A C# program which uses a delegate to call an asynchronous method with a callback method performed after the async method finishes."

This program uses a delegate to call an async method, then continues to do work on current thread until the callback method notifies that the async method has finished (or the async method times-out), or the work on the current thread is finished (then current thread just wait for async method to finish).

There is 5 seconds of work on the current thread (thread 1) and 10 seconds of work for the thread running the delegated async method (thread3). There is an additional 3 seconds of work in the callback method (thread 3). The current thread finished its work first. The current thread then waits for the async method to finish or time-out. If the async method finishes, it causes the execution of the callback method. The current thread continues to wait until the callback method is finished or times-out. The total run-time is a little over 14 seconds. The following C# features are used in the sample code:

  1. AsyncCallback Delegate - References a method to be called when a corresponding asynchronous operation completes.
  2. IAsyncResult Interface - Represents the status of an asynchronous operation.
  3. BeginInvoke() - Executes a delegate asynchronously on the thread that the control's underlying handle was created on
  4. EndInvoke() - Retrieves the return value of the asynchronous operation represented by the IAsyncResult passed.

    Async Method with Callback

    using System;
    using System.Threading;
    using System.Diagnostics;


    namespace DelegateCallback
    {
        delegate void TheDelegate(string s);

        static class StatClass
        {
            public static bool AsychMethodIsFinished { get; set; }
            public static bool CallBackIsFinished { get; set; }

            static StatClass() { CallBackIsFinished = AsychMethodIsFinished = false; }
           
            static void CallWhenFinished(IAsyncResult asyncRes)
            {
                System.Console.WriteLine("CallWhenFinished: Started on thread id: {0} at: {1}",
                                          Thread.CurrentThread.ManagedThreadId,
                                          DateTime.Now.ToString("hh:mm:ss tt", System.Globalization.DateTimeFormatInfo.InvariantInfo));
                System.Threading.Thread.Sleep(3000);

                // Passed original delegate in the asyncState parameter
                TheDelegate parmDelegate = (TheDelegate)asyncRes.AsyncState;
                parmDelegate.EndInvoke(asyncRes);

                Console.WriteLine("Asynchronous Call Completed.");
                System.Console.WriteLine("CallWhenFinished: Ended on thread id: {0} at: {1}",
                                          Thread.CurrentThread.ManagedThreadId,
                                          DateTime.Now.ToString("hh:mm:ss tt", System.Globalization.DateTimeFormatInfo.InvariantInfo));
                CallBackIsFinished = true;
            }


            public static void DelMethod(TheDelegate parmDelegate)
            {
                System.Console.WriteLine("DelMethod: Started on thread id: {0} at: {1}",
                                          Thread.CurrentThread.ManagedThreadId,
                                          DateTime.Now.ToString("hh:mm:ss tt", System.Globalization.DateTimeFormatInfo.InvariantInfo));
                /******************************
                 * Asynchronous Delegate Call *
                 ******************************/
                // Send delegate object as state parameter (last parm)
                IAsyncResult asyncRes = parmDelegate.BeginInvoke("I am the Delegate Parameter - Asynchronous", new AsyncCallback(CallWhenFinished), parmDelegate);

                // 5 Seconds of Work
                for (int i = 0; i < 5; i++)
                    System.Threading.Thread.Sleep(1000);

    //            parmDelegate.EndInvoke(asyncRes);
                System.Console.WriteLine("\nDelMethod: Ended on thread id: {0} at: {1}",
                                          Thread.CurrentThread.ManagedThreadId,
                                          DateTime.Now.ToString("hh:mm:ss tt", System.Globalization.DateTimeFormatInfo.InvariantInfo));
            }
        }

        class Program
        {
            static void Header()
            {
                System.Console.WriteLine("*********************************************************");
                System.Console.WriteLine("***        Asynchronous Method with Callback         ***");
                System.Console.WriteLine("*********************************************************\n");
            }

            static void TheMethod(string s)
            {
                System.Console.WriteLine("TheMethod: Started on thread id: {0} at: {1}",
                              Thread.CurrentThread.ManagedThreadId,
                              DateTime.Now.ToString("hh:mm:ss tt", System.Globalization.DateTimeFormatInfo.InvariantInfo));
                Console.WriteLine(s);

                // 10 Seconds of Work
                int i;
                for (i = 0; i < 10; i++)
                    System.Threading.Thread.Sleep(1000);

                System.Console.WriteLine("TheMethod: Ended on thread id: {0} at: {1}",
                              Thread.CurrentThread.ManagedThreadId,
                              DateTime.Now.ToString("hh:mm:ss tt", System.Globalization.DateTimeFormatInfo.InvariantInfo));
                StatClass.AsychMethodIsFinished = true;
            }


            static void Main()
            {
                Stopwatch myStopWatch = new Stopwatch();
                myStopWatch.Start();
                Program.Header();
                System.Console.WriteLine("Main: Started on thread id: {0} at: {1}",
                              Thread.CurrentThread.ManagedThreadId,
                              DateTime.Now.ToString("hh:mm:ss tt", System.Globalization.DateTimeFormatInfo.InvariantInfo));

                // Define the delegate
                TheDelegate myDelegate1 = new TheDelegate(TheMethod);

                // Invoke the delegate
                StatClass.DelMethod(myDelegate1);

                int waitSeconds = 0;
                while ((!StatClass.CallBackIsFinished) && (waitSeconds < 30))
                {
                    if (!StatClass.AsychMethodIsFinished)
                        Console.WriteLine("Main: Waiting for asych method to finish");
                    else
                        Console.WriteLine("Main: Waiting for callback to finish");
                   waitSeconds++;
                   System.Threading.Thread.Sleep(1000);
                }
                System.Console.WriteLine("Main: Ended on thread id: {0} at: {1}",
                              Thread.CurrentThread.ManagedThreadId,
                              DateTime.Now.ToString("hh:mm:ss tt", System.Globalization.DateTimeFormatInfo.InvariantInfo));
                myStopWatch.Stop();
                System.Console.WriteLine("\nTotal run time is: {0}\n", myStopWatch.Elapsed);
            }
        }
    }