Dela via


Så här gör du: Anropa operationer asynkront med hjälp av en kanalfabrik

Det här avsnittet beskriver hur en klient kan komma åt en tjänståtgärd asynkront när du använder ett ChannelFactory<TChannel>-baserat klientprogram. (När du använder ett System.ServiceModel.ClientBase<TChannel> objekt för att anropa en tjänst kan du använda den händelsedrivna asynkrona samtalsmodellen. Mer information finns i Så här anropar du tjänståtgärder asynkront. Mer information om den händelsebaserade asynkrona samtalsmodellen finns i Händelsebaserat Asynkront mönster (EAP).)

Tjänsten i det här avsnittet implementerar ICalculator gränssnittet. Klienten kan anropa åtgärderna i det här gränssnittet asynkront, vilket innebär att åtgärder som Add är uppdelade i två metoder, BeginAdd och EndAdd, vars tidigare initierar anropet och det senare hämtar resultatet när åtgärden slutförs. Ett exempel som visar hur du implementerar en åtgärd asynkront i en tjänst finns i Så här implementerar du en asynkron tjänståtgärd. Mer information om synkrona och asynkrona åtgärder finns i Synkrona och Asynkrona åtgärder.

Förfarande

Anropa WCF-tjänståtgärder asynkront

  1. Kör verktyget ServiceModel Metadata Utility (Svcutil.exe) med alternativet /async som du ser i följande kommando.

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

    Detta genererar en asynkron klientversion av tjänstkontraktet för åtgärden.

  2. Skapa en motringningsfunktion som ska anropas när den asynkrona åtgärden är klar, som du ser i följande exempelkod.

    static void AddCallback(IAsyncResult ar)
    {
        double result = ((CalculatorClient)ar.AsyncState).EndAdd(ar);
        Console.WriteLine($"Add Result: {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. Om du vill komma åt en tjänståtgärd asynkront skapar du klienten och anropar Begin[Operation] (till exempel BeginAdd) och anger en återanropsfunktion, som du ser i följande exempelkod.

    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({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)
    

    När återanropsfunktionen körs anropar End<operation> klienten (till exempel EndAdd) för att hämta resultatet.

Exempel

Tjänsten som används med klientkoden som används i föregående procedur implementerar ICalculator gränssnittet enligt följande kod. På tjänstsidan anropas kontraktets operationer Add och Subtract synkront av Windows Communication Foundation (WCF) körmiljön, även om de föregående stegen på klienten anropas asynkront. Åtgärderna Multiply och Divide används för att anropa tjänsten asynkront på tjänstsidan, även om klienten anropar dem synkront. I det här exemplet anges egenskapen AsyncPattern till true. Den här egenskapsinställningen, i kombination med implementeringen av det asynkrona .NET Framework-mönstret, instruerar körningen att anropa åtgärden asynkront.

[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