如何:使用回调技术实现异步 Web 服务客户端

本主题专门介绍一项旧有技术。现在应通过使用以下链接来创建 XML Web 服务和 XML Web 服务客户端: Windows Communication Foundation.

回调技术是一种可实现与 Web 服务方法进行异步通信的 Web 服务客户端的方法(虽然该方法可能用于同步访问)。将在主题“与 XML Web services 进行异步通信”中解释该技术。

此示例基于具有 Factorize 方法的 Web 服务类 PrimeFactorizer,Wsdl.exe 工具已经为该类生成了两个异步客户端代理方法:BeginFactorizeEndFactorize

实现回调技术

  1. 定义一个实现 AsyncCallback 委托的回调函数。

    public static void FactorizeCallback(IAsyncResult ar)
    
    Public Shared Sub FactorizeCallback(ar As IAsyncResult)
    
  2. 实例化 AsyncCallback 委托。

    AsyncCallback cb = new AsyncCallback(TestCallback.FactorizeCallback);
    
    Dim cb as AsyncCallback 
    cb = new AsyncCallback(AddressOf TestCallback.FactorizeCallback)
    
  3. 调用 Begin 方法,将回调函数作为第二个参数传递,将提供状态的对象(在此示例中为 PrimeFactorizer 的客户端实现)作为第三个参数传递。

    IAsyncResult ar = pf.BeginFactorize(factorizableNum, cb, pf);
    
    Dim ar As IAsyncResult = pf.BeginFactorize(factorizableNum, _
                                                         cb, pf)
    
  4. 检查 Begin 方法返回的 IAsyncResult 上的 IsCompleted 属性。在客户端收到来自服务器的响应后,值被设置为 true

  5. 在回调函数内,访问状态对象。IAsyncState 参数的 AsyncState 属性将传递的对象作为 Begin 方法的第三个参数。

    PrimeFactorizer pf = (PrimeFactorizer) ar.AsyncState;
    
    Dim pf As PrimeFactorizer = ar.AsyncState
    
  6. 在回调函数内,对在上一个步骤中获得的状态对象调用 End 方法。

    long[] results = pf.EndFactorize(ar);
    
    Dim results() as Long
    results = pf.EndFactorize(ar)
    

示例

using System;
using System.Runtime.Remoting.Messaging;
using MyFactorize;

class TestCallback
 {           
      public static void Main(){
            long factorizableNum = 12345;
            PrimeFactorizer pf = new PrimeFactorizer();

            //Instantiate an AsyncCallback delegate to use as a parameter
            //in the BeginFactorize method.
            AsyncCallback cb = new AsyncCallback(TestCallback.FactorizeCallback);

          // Begin the Async call to Factorize, passing in our
          // AsyncCalback delegate and a reference
          // to our instance of PrimeFactorizer.
            IAsyncResult ar = pf.BeginFactorize(factorizableNum, cb, pf);
            
            // Keep track of the time it takes to complete the async call
            // as the call proceeds.
         int start = DateTime.Now.Second;
         int currentSecond = start;
         while (!ar.IsCompleted){
            if (currentSecond < DateTime.Now.Second) {
                  currentSecond = DateTime.Now.Second;
                  Console.WriteLine("Seconds Elapsed..." + (currentSecond - start).ToString() );
            }
         }
         // Once the call has completed, you need a method to ensure the
         // thread executing this Main function 
         // doesn't complete prior to the call-back function completing.
         Console.Write("Press Enter to quit");
         int quitchar = Console.Read();
      }
      // Set up a call-back function that is invoked by the proxy class
      // when the asynchronous operation completes.
      public static void FactorizeCallback(IAsyncResult ar)
      {
          // You passed in our instance of PrimeFactorizer in the third
          // parameter to BeginFactorize, which is accessible in the
          // AsyncState property.
          PrimeFactorizer pf = (PrimeFactorizer) ar.AsyncState;
          long[] results;

          // Get the completed results.
            results = pf.EndFactorize(ar);
          
          //Output the results.
            Console.Write("12345 factors into: ");
            int j;
            for (j = 0; j<results.Length;j++){
                  if (j == results.Length - 1)
                      Console.WriteLine(results[j]);
                  else 
                      Console.Write(results[j] + ", ");
            }
      }
}
Imports System
Imports System.Runtime.Remoting.Messaging
Imports MyFactorize

Public Class TestCallback
    Public Shared Sub Main()
       Dim factorizableNum As Long = 12345
       Dim pf As PrimeFactorizer = new PrimeFactorizer()

       'Instantiate an AsyncCallback delegate to use as a 
       'parameter
       ' in the BeginFactorize method.
       Dim cb as AsyncCallback 
       cb = new AsyncCallback(AddressOf TestCallback.FactorizeCallback)

     ' Begin the Async call to Factorize, passing in the
     ' AsyncCallback delegate and a reference to our instance
     ' of PrimeFactorizer.
       Dim ar As IAsyncResult = pf.BeginFactorize(factorizableNum, _
                                                     cb, pf)
            
     ' Keep track of the time it takes to complete the async call as
     ' the call proceeds.
       Dim start As Integer = DateTime.Now.Second
       Dim currentSecond As Integer = start
       Do while (ar.IsCompleted = false)
          If (currentSecond < DateTime.Now.Second) Then
                currentSecond = DateTime.Now.Second
                Console.WriteLine("Seconds Elapsed..." + 
                      (currentSecond - start).ToString() )
          End If
       Loop

      ' Once the call has completed, you need a method to ensure the
      ' thread executing this Main function 
      ' doesn't complete prior to the callback function completing.
       Console.Write("Press Enter to quit")
       Dim quitchar As Integer = Console.Read()
    End Sub

    ' Set up the call-back function that is invoked by the proxy 
    ' class when the asynchronous operation completes.
    Public Shared Sub FactorizeCallback(ar As IAsyncResult)
    
       ' You passed in the instance of PrimeFactorizer in the third
       ' parameter to BeginFactorize, which is accessible in the
       ' AsyncState property.
         Dim pf As PrimeFactorizer = ar.AsyncState
         Dim results() as Long

       ' Get the completed results.
         results = pf.EndFactorize(ar)
        
       'Output the results.
         Console.Write("12345 factors into: ")
         Dim j as Integer
         For j = 0 To results.Length - 1
              If  j = (results.Length - 1) Then
                   Console.WriteLine(results(j) )
              Else 
                   Console.Write(results(j).ToString + ", ")
              End If
        Next j         
     End Sub      
End Class

另请参见

任务

如何:使用等待技术实现异步 Web 服务客户端
如何:从 Web 服务客户端进行异步调用

概念

与 XML Web services 进行异步通信
生成 XML Web services 客户端

其他资源

创建 XML Web services 客户端