共用方式為


HOW TO:以非同步方式呼叫 WCF 服務作業

本主題涵蓋用戶端如何能夠非同步地存取服務作業。本主題中的服務會實作 ICalculator 介面。用戶端可以透過使用事件驅動的非同步呼叫模型,以非同步方式在這個介面上呼叫作業。(如需事件架構非同步呼叫模型的詳細資訊,請參閱Multithreaded Programming with the Event-based Asynchronous Pattern)。如需示範如何在服務中以非同步方式實作作業的範例,請參閱 HOW TO:實作非同步服務作業。如需同步與非同步作業的詳細資訊,請參閱同步和非同步作業

ms730059.note(zh-tw,VS.100).gif注意:
當使用 ChannelFactory 時,不支援事件驅動非同步呼叫模型。如需使用 ChannelFactory 進行非同步呼叫的詳細資訊,請參閱 HOW TO:使用通道處理站以非同步方式呼叫作業

程序

若要以非同步方式呼叫 WCF 服務作業

  1. 配合 /async/tcv:Version35 命令選項執行 ServiceModel 中繼資料公用程式工具 (Svcutil.exe) 工具,如下列命令所示。

    svcutil /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples https://localhost:8000/servicemodelsamples/service/mex /a /tcv:Version35
    

    除了同步作業和標準委派架構非同步作業外,這還會產生包含下列內容的 WCF 用戶端類別:

    • 兩個 <operationName>Async 作業,可與事件架構非同步呼叫方法一起使用。例如:

      Public Overloads Sub AddAsync(ByVal n1 As Double, ByVal n2 As Double)
          Me.AddAsync(n1, n2, Nothing)
      End Sub
      
      Public Overloads Sub AddAsync(ByVal n1 As Double, ByVal n2 As Double, ByVal userState As Object)
          If (Me.onBeginAddDelegate Is Nothing) Then
              Me.onBeginAddDelegate = AddressOf Me.OnBeginAdd
          End If
          If (Me.onEndAddDelegate Is Nothing) Then
              Me.onEndAddDelegate = AddressOf Me.OnEndAdd
          End If
          If (Me.onAddCompletedDelegate Is Nothing) Then
              Me.onAddCompletedDelegate = AddressOf Me.OnAddCompleted
          End If
          MyBase.InvokeAsync(Me.onBeginAddDelegate, New Object() {n1, n2}, Me.onEndAddDelegate, Me.onAddCompletedDelegate, userState)
      End Sub
      
      public void AddAsync(double n1, double n2)
      {
          this.AddAsync(n1, n2, null);
      }
      
      public void AddAsync(double n1, double n2, object userState)
      {
          if ((this.onBeginAddDelegate == null))
          {
              this.onBeginAddDelegate = new BeginOperationDelegate(this.OnBeginAdd);
          }
          if ((this.onEndAddDelegate == null))
          {
              this.onEndAddDelegate = new EndOperationDelegate(this.OnEndAdd);
          }
          if ((this.onAddCompletedDelegate == null))
          {
              this.onAddCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnAddCompleted);
          }
          base.InvokeAsync(this.onBeginAddDelegate, new object[] {
                      n1,
                      n2}, this.onEndAddDelegate, this.onAddCompletedDelegate, userState);
      }
      
    • <operationName>Completed 格式的作業完成事件,可與事件架構非同步呼叫方法一起使用。例如:

      Public Event AddCompleted As System.EventHandler(Of AddCompletedEventArgs)
      
      public event System.EventHandler<AddCompletedEventArgs> AddCompleted;
      
    • 每個作業的 System.EventArgs 型別 (格式為 <operationName>CompletedEventArgs),可與事件架構非同步呼叫方法一起使用。例如:

      <System.Diagnostics.DebuggerStepThroughAttribute(),  _
       System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")>  _
      Partial Public Class AddCompletedEventArgs
          Inherits System.ComponentModel.AsyncCompletedEventArgs
      
          Private results() As Object
      
          Public Sub New(ByVal results() As Object, ByVal exception As System.Exception, ByVal cancelled As Boolean, ByVal userState As Object)
              MyBase.New(exception, cancelled, userState)
              Me.results = results
          End Sub
      
          Public ReadOnly Property Result() As Double
              Get
                  MyBase.RaiseExceptionIfNecessary
                  Return CType(Me.results(0),Double)
              End Get
          End Property
      End Class
      
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
      public partial class AddCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
      {
          private object[] results;
      
          public AddCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : 
                  base(exception, cancelled, userState)
          {       this.results = results;         }
      
          public double Result
          {
              get            {
                  base.RaiseExceptionIfNecessary();
                  return ((double)(this.results[0]));
              }
          }
      }
      
  2. 在呼叫應用程式中,建立要在非同步作業完成時呼叫的回呼方法,如下列範例程式碼所示。

    ' Asynchronous callbacks for displaying results.
    Private Shared Sub AddCallback(ByVal sender As Object, ByVal e As AddCompletedEventArgs)
    
        Console.WriteLine("Add Result: {0}", e.Result)
    
    End Sub
    
    // Asynchronous callbacks for displaying results.
    static void AddCallback(object sender, AddCompletedEventArgs e)
    {
        Console.WriteLine("Add Result: {0}", e.Result);
    }
    
  3. 在呼叫作業之前,先使用型別為 <operationName>EventArgs 的新泛型 System.EventHandler,將處理常式方法 (在上述步驟中建立) 加入至 <operationName>Completed 事件。接著,呼叫 <operationName>Async 方法。例如:

    ' AddAsync
    Dim value1 As Double = 100
    Dim value2 As Double = 15.99
    AddHandler client.AddCompleted, AddressOf AddCallback
    client.AddAsync(value1, value2)
    Console.WriteLine("Add({0},{1})", value1, value2)
    
    // AddAsync
    double value1 = 100.00D;
    double value2 = 15.99D;
    client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback);
    client.AddAsync(value1, value2);
    Console.WriteLine("Add({0},{1})", value1, value2);
    

範例

ms730059.note(zh-tw,VS.100).gif注意:
事件架構非同步模型的設計方針指出,如果傳回多個值,則其中一個值會傳回做為 Result 屬性,其他值則傳回做為 EventArgs 物件上的屬性。這樣做的結果就是,如果用戶端使用事件架構非同步命令選項匯入中繼資料,且作業傳回多個值,則預設 EventArgs 物件會傳回一個值做為 Result 屬性,而其餘則做為 EventArgs 物件的屬性。如果您要接收訊息物件做為 Result 屬性,並讓傳回值做為該物件的屬性,請使用 /messageContract 命令選項。這會產生一個簽章,此簽章會將回應訊息傳回做為 EventArgs 物件的 Result 屬性。然後,所有的內部傳回值都成為回應訊息物件的屬性。

Imports System

Namespace Microsoft.ServiceModel.Samples

    ' The service contract is defined in generatedClient.vb, generated from the service by the svcutil tool.

    Class Client

        Public Shared Sub Main()

            Console.WriteLine("Press <ENTER> to terminate client once the output is displayed.")
            Console.WriteLine()

            ' Create a client
            Dim client As New CalculatorClient()

            ' AddAsync
            Dim value1 As Double = 100
            Dim value2 As Double = 15.99
            AddHandler client.AddCompleted, AddressOf AddCallback
            client.AddAsync(value1, value2)
            Console.WriteLine("Add({0},{1})", value1, value2)

            ' SubtractAsync
            value1 = 145
            value2 = 76.54
            AddHandler client.SubtractCompleted, AddressOf SubtractCallback
            client.SubtractAsync(value1, value2)
            Console.WriteLine("Subtract({0},{1})", value1, value2)

            ' Multiply
            value1 = 9
            value2 = 81.25
            Dim result As Double = client.Multiply(value1, value2)
            Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result)

            ' Divide
            value1 = 22
            value2 = 7
            result = client.Divide(value1, value2)
            Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result)
            Console.ReadLine()

            'Closing the client gracefully closes the connection and cleans up resources
            client.Close()

        End Sub
        ' Asynchronous callbacks for displaying results.
        Private Shared Sub AddCallback(ByVal sender As Object, ByVal e As AddCompletedEventArgs)

            Console.WriteLine("Add Result: {0}", e.Result)

        End Sub
        Private Shared Sub SubtractCallback(ByVal sender As Object, ByVal e As SubtractCompletedEventArgs)

            Console.WriteLine("Subtract Result: {0}", e.Result)

        End Sub

    End Class

End Namespace
using System;

namespace Microsoft.ServiceModel.Samples
{
    // The service contract is defined in generatedClient.cs, generated from the service by the svcutil tool.

    class Client
    {
        static void Main()
        {
            Console.WriteLine("Press <ENTER> to terminate client once the output is displayed.");
            Console.WriteLine();

            // Create a client
            CalculatorClient client = new CalculatorClient();

            // AddAsync
            double value1 = 100.00D;
            double value2 = 15.99D;
            client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback);
            client.AddAsync(value1, value2);
            Console.WriteLine("Add({0},{1})", value1, value2);

            // SubtractAsync
            value1 = 145.00D;
            value2 = 76.54D;
            client.SubtractCompleted += new EventHandler<SubtractCompletedEventArgs>(SubtractCallback);
            client.SubtractAsync(value1, value2);
            Console.WriteLine("Subtract({0},{1})", value1, value2);

            // Multiply
            value1 = 9.00D;
            value2 = 81.25D;
            double result = client.Multiply(value1, value2);
            Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);

            // Divide
            value1 = 22.00D;
            value2 = 7.00D;
            result = client.Divide(value1, value2);
            Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);

            Console.ReadLine();

            //Closing the client gracefully closes the connection and cleans up resources
            client.Close();
        }

        // Asynchronous callbacks for displaying results.
        static void AddCallback(object sender, AddCompletedEventArgs e)
        {
            Console.WriteLine("Add Result: {0}", e.Result);
        }

        static void SubtractCallback(object sender, SubtractCompletedEventArgs e)
        {
            Console.WriteLine("Subtract Result: {0}", e.Result);
        }
    }
}

另請參閱

工作

非同步