Using Delegates

With asynchronous programming, the caller must define the delegate when calling a method, if the caller uses a delegate. In the following code sample, the delegate is first defined, then an instance of it created, and then it is called. The sample below shows the caller defining a pattern for the invoking the Factorize method asynchronously:

using System;
using System.Runtime.Remoting;

public delegate bool FactorizingAsyncDelegate(
         int factorizableNum, 
         ref int primefactor1,
         ref int primefactor2);

// This is a class that receives a callback when the results are available.
public class ProcessFactorizedNumber
{
   private int _ulNumber;

   public ProcessFactorizedNumber(int number)
   {
      _ulNumber = number;
   }

   // Note the qualifier one-way.
   [OneWayAttribute()]
   public void FactorizedResults(IAsyncResult ar)
   {
      int factor1=0, factor2=0; 

      // Extract the delegate from the AsyncResult.  
      FactorizingAsyncDelegate fd = 
         (FactorizingAsyncDelegate) ((AsyncResult)ar).AsyncDelegate;
      // Obtain the result.
      fd.EndInvoke(ref factor1, ref factor2, ar);

      // Output the results.
      Console.WriteLine("On CallBack: Factors of {0} : {1} {2}", 
                    _ulNumber, factor1, factor2);
   }
}
Asynchronous Variation 1 – call
// The Asynchronous Variation 1 call, calls
// the ProcessFactorizedNumber.FactorizedResults callback 
// when the call completes.
public void FactorizeNumber1()
{
   // The following is the Client code.
   PrimeFactorizer pf = new PrimeFactorizer();
   FactorizingAsyncDelegate fd = new FactorizingAsyncDelegate (pf.Factorize);

   // Asynchronous Variation 1
   int factorizableNum = 1000589023, temp=0; 

   // Create an instance of the class that is going 
   // to be called when the call completes.
   ProcessFactorizedNumber fc = new ProcessFactorizedNumber(factorizableNum);

   // Define the AsyncCallback delegate.
   AsyncCallback cb = new AsyncCallback(fc.FactorizedResults);

   // You can use any object as the state object.
   Object state = new Object();

   // Asynchronously invoke the Factorize method on pf.
   IAsyncResult ar = fd.BeginInvoke(
                        factorizableNum, 
                        ref temp, 
                        ref temp, 
                        cb, 
                        state); 

   //
   // Do some other useful work.
   //. . .
}
Asynchronous Variation 2
// Asynchronous Variation 2
// Waits for the result.
public void FactorizeNumber2()
{
   // The following is the Client code.
   PrimeFactorizer pf = new PrimeFactorizer();
   FactorizingAsyncDelegate fd = new FactorizingAsyncDelegate (pf.Factorize);

   // Asynchronous Variation 1
   int factorizableNum = 1000589023, temp=0; 

   // Create an instance of the class that is going 
   // to called when the call completes.
   ProcessFactorizedNumber fc = new ProcessFactorizedNumber(factorizableNum);

   // Define the AsyncCallback delegate.
   AsyncCallback cb = 
   new AsyncCallback(fc.FactorizedResults);

   // You can use any object as the state object.
   Object state = new Object();

   // Asynchronously invoke the Factorize method on pf.
   IAsyncResult ar = fd.BeginInvoke(
                     factorizableNum, 
                     ref temp, 
                     ref temp, 
                     null, 
                     null); 

   ar.AsyncWaitHandle.WaitOne(10000, false);

   if (ar.IsCompleted)
   {
      int factor1=0, factor2=0; 

      // Obtain the result.
      fd.EndInvoke(ref factor1, ref factor2, ar);

      // Output the results.

      Console.WriteLine("Sequential : Factors of {0} : {1} {2}", 
                    factorizableNum, factor1, factor2);

   }
}

Note   Calling EndInvoke before the asynchronous operation is complete will block the caller. Calling it the second time with the same IAsyncResult is undefined.

See Also

Asynchronous Delegates | Asynchronous Delegates Programming Sample