Friday, June 6, 2014

Asynchronous Programming Using Delegates

Delegated allow you to call any synchronous method asynchronously. In this post I will discuss way of doing this.

BeginInvoke() :

When a delegate is called using BeginInvoke it has same parameters as the method that you want to execute and two other parameters.

  1. AsyncCallback :delegate that references a method to be called when the asynchronous call completes
  2. Sender Object: a user-defined object that passes information into the callback method

lets see how this could be done step by step.

Step 1: Define delegate & call it asynchronously

As the first step you can do the followings.

  1. Define a delegate with same signature as the method to be called asynchronously
  2. Assign the method to be called asynchronously to the delegate
  3. Invoke the delegate asynchronously

See the sample code here:

  1. //Define a delegate with same signature as the method to be called asynchronously
  2.   private delegate void UpdateWorkLogHandler(int hours, string workType);
  3.   static void Main(string[] args)
  4.   {
  5.       DoWork(10, "Development");
  6.   }
  7.  
  8.   public static void DoWork(int hours, string workType)
  9.   {
  10.       //Assign the method to be called asynchronously to the delegate
  11.       UpdateWorkLogHandler updateWorkLogHandler = UpdateWorkLog;
  12.    
  13.       //Invoke the delegate asynchronously
  14.       updateWorkLogHandler.BeginInvoke(hours, workType, null, null);
  15.       Console.WriteLine("Work Completed!. Log updating in progress");
  16.       Console.ReadLine();
  17.   }
  18.  
  19.   public static void UpdateWorkLog(int hours, string workType)
  20.   {
  21.       System.Threading.Thread.Sleep(1000);
  22.  
  23.       Console.WriteLine("Work log updated!");
  24.       Console.ReadLine();
  25.   }

Output Window :

image

You can see here before completion of UpdateWorkLog method, programs has printed the “Work Completed!. Log updating in progress”. It is because as UpdateWorkLog  is called asynchronously rest of the code in DoWork method is been executed. If you have invoked the delegate without BeginInvoke output will be the following.

image

Step 2: With Callback

In case if you want to know whether that method is executed and call back to a method which you define & then execute some other logic you can assign a callback method on BeginInvoke as below.

  1. //Define a delegate with same signature as the method to be called asynchronously
  2.         private delegate void UpdateWorkLogHandler(int hours, string workType);
  3.       
  4.         static void Main(string[] args)
  5.         {
  6.             DoWork(10, "Development");
  7.         }
  8.  
  9.         public static void DoWork(int hours, string workType)
  10.         {
  11.             //Assign the method to be called asynchronously to the delegate
  12.             UpdateWorkLogHandler updateWorkLogHandler = UpdateWorkLog;
  13.           
  14.             //Invoke the delegate asynchronously
  15.             updateWorkLogHandler.BeginInvoke(hours, workType, UpdateWorkLogCompleted, null);
  16.             Console.WriteLine("Work Completed!. Log updating in progress");
  17.             Console.ReadLine();
  18.         }
  19.  
  20.         //Callback Method
  21.         public static void UpdateWorkLogCompleted(IAsyncResult ar)
  22.         {
  23.             Console.WriteLine("Work log updated Callback called");
  24.             Console.ReadLine();
  25.         }
  26.         public static void UpdateWorkLog(int hours, string workType)
  27.         {
  28.             System.Threading.Thread.Sleep(1000);
  29.             Console.WriteLine("Work log updated");
  30.            
  31.         }

Output Window:

image

Step 3: With EndInvoke

In case if you need a return value from the asynchronously called method you can use EndInvoke.

The EndInvoke method retrieves the results of the asynchronous call. It can be called any time after BeginInvoke. If the asynchronous call has not completed, EndInvoke blocks the calling thread until it completes.

See the sample code below. It take the return value and then do the rest of the execution.


  //Define a delegate with same signature as the method to be called asynchronously
  private delegate bool UpdateWorkLogHandler(int hours, string workType);

  static void Main(string[] args)
  {
      DoWork(10, "Development");
  }

  public static void DoWork(int hours, string workType)
  {
      //Assign the method to be called asynchronously to the delegate
      UpdateWorkLogHandler updateWorkLogHandler = UpdateWorkLog;
    
      //Invoke the delegate asynchronously
     IAsyncResult result= updateWorkLogHandler.BeginInvoke(hours, workType,null,null);
     
      Console.WriteLine("Work Completed!. Log updating in progress");

      // Call EndInvoke and get the returned value
      bool returnedValue = updateWorkLogHandler.EndInvoke(result);
      UpdateWorkLogCompleted(returnedValue);

      Console.WriteLine("Do Work Completed");
      Console.ReadLine();
  }

  //Callback Method
  public static void UpdateWorkLogCompleted(bool result)
  {
      Console.WriteLine("Work log updated Callback called Result:"+ result);
    
  }
  public static bool UpdateWorkLog(int hours, string workType)
  {
      System.Threading.Thread.Sleep(1000);
      Console.WriteLine("Work log updated");
      return true;

  }

Output Window :

image

So can see here it has received the return value. Also the it did not execute the rest of the code until after EndInvoke until it received the returned value.

Hope this helps you.

Happy Coding !!!!!

No comments :

Post a Comment