Поделиться через


Пример асинхронного программирования делегатов

Обновлен: Ноябрь 2007

В следующем примере кода демонстрируется использование асинхронного программирования в .NET с применением класса, выполняющего расчет простых множителей для нескольких чисел. В этом примере определяется класс с единственным методом Factorize, который вычисляет простые множители для заданного числа. В этом примере также определяется делегат с именем AsyncFactorCaller, подпись которого совпадает с подписью метода Factorize. Этот делегат используется методами класса DemonstrateAsyncPattern для асинхронного вызова метода Factorize. В методе FactorizeNumberUsingCallback демонстрируется использование делегата AsyncCallback для завершения асинхронной операции и получения результатов. В методе FactorizeNumberAndWait демонстрируется периодический опрос, который позволяет определить, была ли завершена операция.

Пример

Imports System
Imports System.Threading
Imports System.Runtime.Remoting.Messaging

Namespace Examples.AdvancedProgramming.AsynchronousOperations

    ' Create a class that factors a number.
    Public Class PrimeFactorFinder
       Public Shared Function Factorize( _
                    ByVal number as Integer, _
                    Byref primefactor1 as Integer, _
                    Byref primefactor2 as Integer) as Boolean
          primefactor1 = 1
          primefactor2 = number

          ' Factorize using a low-tech approach.
          For i as Integer =2 To number-1
             If 0 =  (number MOD i)
                primefactor1 = i
                primefactor2 = number / i
                Exit For
             End If
          Next i
          If 1 = primefactor1
             Return False
          Else
             Return True
          End If
       End Function
    End Class

    ' Create an asynchronous delegate that matches the Factorize method.
    Public delegate Function AsyncFactorCaller ( _
             number as Integer, _
             ByRef primefactor1 as Integer, _
             ByRef primefactor2 as Integer) as Boolean

    Public Class DemonstrateAsyncPattern
              ' The waiter object is used to keep the main application thread
              ' from terminating before the callback method completes.
              Dim waiter as ManualResetEvent 
        ' Define the method that is invoked when the results are available.
        Public Sub FactorizedResults(result as IAsyncResult)
              Dim factor1 as Integer =0
              Dim factor2 as Integer =0

              ' Extract the delegate from the 
              ' System.Runtime.Remoting.Messaging.AsyncResult.
              Dim ar as AsyncResult = CType (result, AsyncResult)
              Dim delegateObject as Object = ar.AsyncDelegate
              Dim factorDelegate as AsyncFactorCaller =  _
                    CType(delegateObject, AsyncFactorCaller)

              Dim number as Integer = CType(result.AsyncState, Integer)
              Dim answer as Boolean

              ' Obtain the result.
              answer = factorDelegate.EndInvoke(factor1, factor2, result)
              ' Output the results.
              Console.WriteLine("On CallBack: Factors of {0} : {1} {2} - {3}", _
                  number, factor1, factor2, answer)
             waiter.Set()
           End Sub

       ' The following method demonstrates the asynchronous pattern using a callback method.
       Public Sub FactorizeNumberUsingCallback()
          Dim  factorDelegate as AsyncFactorCaller
          Dim result as IAsyncResult
          Dim callback as AsyncCallback
          Dim number as Integer = 1000589023
          Dim temp as Integer = 0 

         ' Waiter will keep the main application thread from 
         '' ending before the callback completes because
         ' the main thread blocks until the waiter is signaled
         ' in the callback.
          waiter = new ManualResetEvent(False)
          factorDelegate = AddressOf PrimeFactorFinder.Factorize
          ' Define the AsyncCallback delegate.
          callBack = new AsyncCallback (AddressOf FactorizedResults)

          ' Asynchronously invoke the Factorize method.
          result = factorDelegate.BeginInvoke( _
                               number, _
                               temp, _
                               temp, _
                               callBack, _
                               number) 
       End Sub

       ' The following method demonstrates the asynchronous pattern 
       ' using a BeginInvoke, followed by waiting with a time-out.
       Public Sub FactorizeNumberAndWait()
           Dim factorDelegate as AsyncFactorCaller
           Dim result as IAsyncResult

           factorDelegate = AddressOf PrimeFactorFinder.Factorize

          Dim number as Integer = 1000589023
          Dim temp as Integer = 0 

          ' Asynchronously invoke the Factorize method.
          result = factorDelegate.BeginInvoke( _
                            number, _
                            temp, _ 
                            temp, _
                            Nothing, _
                            Nothing) 

          Do While result.IsCompleted = False
            ' Do any work you can do before waiting.
            result.AsyncWaitHandle.WaitOne(10000, false)
          Loop
          ' The asynchronous operation has completed.
          Dim factor1 as Integer = 0
          Dim factor2 as Integer = 0
          Dim answer as Boolean
          ' Obtain the result.
          answer = factorDelegate.EndInvoke(factor1, factor2, result)

         ' Output the results.
         Console.WriteLine("Sequential : Factors of {0} : {1} {2} - {3}", _ 
                           number, factor1, factor2, answer)
       End Sub

       Public Shared Sub Main()
          Dim  demonstrator as DemonstrateAsyncPattern
          demonstrator = new DemonstrateAsyncPattern()
          demonstrator.FactorizeNumberUsingCallback()
          demonstrator.FactorizeNumberAndWait()
       End Sub
    End Class
End Namespace
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    // Create a class that factors a number.
    public class PrimeFactorFinder
    {
       public static bool Factorize(
                    int number,
                    ref int primefactor1,
                    ref int primefactor2)
       {
          primefactor1 = 1;
          primefactor2 = number;

          // Factorize using a low-tech approach.
          for (int i=2;i<number;i++)
          {
             if (0 == (number % i))
             {
                primefactor1 = i;
                primefactor2 = number / i;
                break;
             }
          }
          if (1 == primefactor1 )
             return false;
          else
             return true   ;
       }
    }

    // Create an asynchronous delegate that matches the Factorize method.
    public delegate bool AsyncFactorCaller (
             int number, 
             ref int primefactor1,
             ref int primefactor2);

    public class DemonstrateAsyncPattern
    {
        // The waiter object used to keep the main application thread
        // from terminating before the callback method completes.
        ManualResetEvent waiter;

        // Define the method that receives a callback when the results are available.
        public void FactorizedResults(IAsyncResult result)
           {
              int factor1=0;
              int factor2=0; 

              // Extract the delegate from the 
              // System.Runtime.Remoting.Messaging.AsyncResult.
              AsyncFactorCaller factorDelegate = (AsyncFactorCaller)((AsyncResult)result).AsyncDelegate;
              int number = (int) result.AsyncState;
              // Obtain the result.
              bool answer = factorDelegate.EndInvoke(ref factor1, ref factor2, result);
              // Output the results.
              Console.WriteLine("On CallBack: Factors of {0} : {1} {2} - {3}", 
                  number, factor1, factor2, answer);
              waiter.Set();
           }

       // The following method demonstrates the asynchronous pattern using a callback method.
       public void FactorizeNumberUsingCallback()
       {
          AsyncFactorCaller factorDelegate = new AsyncFactorCaller (PrimeFactorFinder.Factorize);
          int number = 1000589023;
          int temp=0; 
          // Waiter will keep the main application thread from 
          // ending before the callback completes because
          // the main thread blocks until the waiter is signaled
          // in the callback.
           waiter = new ManualResetEvent(false);

          // Define the AsyncCallback delegate.
          AsyncCallback callBack = new AsyncCallback(this.FactorizedResults);

          // Asynchronously invoke the Factorize method.
          IAsyncResult result = factorDelegate.BeginInvoke(
                               number, 
                               ref temp, 
                               ref temp, 
                               callBack, 
                               number); 

          // Do some other useful work while 
          // waiting for the asynchronous operation to complete.

          // When no more work can be done, wait.
          waiter.WaitOne();
       }

       // The following method demonstrates the asynchronous pattern 
       // using a BeginInvoke, followed by waiting with a time-out.
       public void FactorizeNumberAndWait()
       {
          AsyncFactorCaller factorDelegate = new AsyncFactorCaller (PrimeFactorFinder.Factorize);

          int number = 1000589023;
          int temp=0; 

          // Asynchronously invoke the Factorize method.
          IAsyncResult result = factorDelegate.BeginInvoke(
                            number, 
                            ref temp, 
                            ref temp, 
                            null, 
                            null); 

          while (!result.IsCompleted)
          {
            // Do any work you can do before waiting.
            result.AsyncWaitHandle.WaitOne(10000, false);
          }
          // The asynchronous operation has completed.
          int factor1=0;
          int factor2=0; 

         // Obtain the result.
         bool answer = factorDelegate.EndInvoke(ref factor1, ref factor2, result);

         // Output the results.
         Console.WriteLine("Sequential : Factors of {0} : {1} {2} - {3}", 
                           number, factor1, factor2, answer);
       }

       public static void Main()
       {
          DemonstrateAsyncPattern demonstrator = new DemonstrateAsyncPattern();
          demonstrator.FactorizeNumberUsingCallback();
          demonstrator.FactorizeNumberAndWait();
       }
    }
}