Vorgehensweise: Asynchrones Aufrufen von Vorgängen mit einer Kanalfactory

In diesem Thema wird beschrieben, wie ein Client auf einen Dienstvorgang asynchron zugreifen kann, wenn eine auf ChannelFactory<TChannel> basierende Clientanwendung verwendet wird. (Wenn Sie ein System.ServiceModel.ClientBase<TChannel>-Objekt verwenden, um einen Dienst aufzurufen, können Sie das ereignisgesteuerte asynchrone Aufrufmodell verwenden. Weitere Informationen finden Sie unter Gewusst wie: Asynchrones Aufrufen von Dienstvorgängen. Weitere Informationen über das ereignisbasierte asynchrone Aufrufmodell finden Sie unter Ereignisbasiertes asynchrones Muster.

Der in diesem Thema behandelte Dienst implementiert die ICalculator-Schnittstelle. Der Client kann die Vorgänge an dieser Schnittstelle asynchron aufrufen. Dies bedeutet, dass Vorgänge wie Add in zwei Methoden aufgeteilt werden, BeginAdd und EndAdd, wobei die erste den Aufruf einleitet und die zweite das Ergebnis abruft, wenn der Vorgang abgeschlossen ist. Ein Beispiel für die asynchrone Implementierung eines Vorgangs in einen Dienst finden Sie unter Gewusst wie: Implementieren eines asynchronen Dienstvorgangs. Ausführliche Informationen zu synchronen und asynchronen Vorgängen finden Sie unter Synchrone und asynchrone Vorgänge.

Prozedur

So rufen Sie WCF-Dienstvorgänge asynchron auf

  1. Führen Sie das ServiceModel Metadata Utility Tool (Svcutil.exe) mit der /async-Option aus, wie im folgenden Befehl gezeigt.

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

    Dies generiert eine asynchrone Clientversion des Dienstvertrags für den Vorgang.

  2. Erstellen Sie eine Rückruffunktion, die aufgerufen wird, wenn der asynchrone Vorgang abgeschlossen ist, wie im folgenden Beispielcode dargestellt.

    static void AddCallback(IAsyncResult ar)
    {
        double result = ((CalculatorClient)ar.AsyncState).EndAdd(ar);
        Console.WriteLine("Add Result: {0}", result);
    }
    
    Private Shared Sub AddCallback(ByVal ar As IAsyncResult)
        Dim result = (CType(ar.AsyncState, CalculatorClient)).EndAdd(ar)
        Console.WriteLine("Add Result: {0}", result)
    End Sub
    
  3. Zum asynchronen Aufrufen eines Dienstvorgangs erstellen Sie den Client, rufen Sie Begin[Operation] auf (z. B. BeginAdd), und geben Sie eine Rückruffunktion an, wie in folgendem Beispielcode dargestellt.

    ChannelFactory<ICalculatorChannel> factory = new ChannelFactory<ICalculatorChannel>();
    ICalculatorChannel channelClient = factory.CreateChannel();
    
    // BeginAdd
    double value1 = 100.00D;
    double value2 = 15.99D;
    
    IAsyncResult arAdd = channelClient.BeginAdd(value1, value2, AddCallback, channelClient);
    Console.WriteLine("Add({0},{1})", value1, value2);
    
    Dim factory As New ChannelFactory(Of ICalculatorChannel)()
    Dim channelClient As ICalculatorChannel = factory.CreateChannel()
    
    ' BeginAdd
    Dim value1 = 100.0R
    Dim value2 = 15.99R
    
    Dim arAdd As IAsyncResult = channelClient.BeginAdd(value1, value2, AddressOf AddCallback, channelClient)
    Console.WriteLine("Add({0},{1})", value1, value2)
    

    Wenn die Rückruffunktion ausgeführt wird, ruft der Client End<operation>EndAdd (z. B. ) auf, um das Ergebnis abzurufen.

Beispiel

Der Dienst, der mit dem im vorhergehenden Verfahren genutzten Clientcode verwendet wird, implementiert die ICalculator-Schnittstelle, wie im folgenden Beispielcode gezeigt. Auf der Seite des Diensts werden die Add- und Subtract-Vorgänge des Vertrags synchron von der Windows Communication Foundation (WCF)-Laufzeit aufgerufen, auch wenn die vorangegangenen Schritte auf dem Client asynchron aufgerufen wurden. Die Multiply- und Divide-Vorgänge werden verwendet, um den Dienst asynchron auf der Seite des Diensts aufzurufen, auch wenn der Client sie synchron aufruft. Im folgenden Beispiel wird die AsyncPattern-Eigenschaft auf true festgelegt. Diese Eigenschaftseinstellung in Verbindung mit der Implementierung des asynchronen .NET Framework-Musters weist die Laufzeit an, den Vorgang asynchron aufzurufen.

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    double Add(double n1, double n2);

    [OperationContract]
    double Subtract(double n1, double n2);

    //Multiply involves some file I/O so we'll make it Async.
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginMultiply(double n1, double n2, AsyncCallback callback, object state);
    double EndMultiply(IAsyncResult ar);

    //Divide involves some file I/O so we'll make it Async.
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginDivide(double n1, double n2, AsyncCallback callback, object state);
    double EndDivide(IAsyncResult ar);
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples")> _
Public Interface ICalculator
    <OperationContract> _
    Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double

    <OperationContract> _
    Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double

    'Multiply involves some file I/O so we'll make it Async.
    <OperationContract(AsyncPattern:=True)> _
    Function BeginMultiply(ByVal n1 As Double, ByVal n2 As Double, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult
    Function EndMultiply(ByVal ar As IAsyncResult) As Double

    'Divide involves some file I/O so we'll make it Async.
    <OperationContract(AsyncPattern:=True)> _
    Function BeginDivide(ByVal n1 As Double, ByVal n2 As Double, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult
    Function EndDivide(ByVal ar As IAsyncResult) As Double
End Interface