Instrukcje: Asynchroniczne wywoływanie operacji usługi WCF
W tym artykule opisano, jak klient może uzyskać dostęp do operacji usługi asynchronicznie. Usługa w tym artykule implementuje ICalculator
interfejs. Klient może wywoływać operacje w tym interfejsie asynchronicznie przy użyciu modelu asynchronicznego wywoływania sterowanego zdarzeniami. (Aby uzyskać więcej informacji na temat modelu asynchronicznego wywoływania opartego na zdarzeniach, zobacz Programowanie wielowątkowe z asynchronicznym wzorcem opartym na zdarzeniach). Przykład pokazujący, jak zaimplementować operację asynchronicznie w usłudze, zobacz Instrukcje: implementowanie asynchronicznej operacji usługi. Aby uzyskać więcej informacji na temat operacji synchronicznych i asynchronicznych, zobacz Operacje synchroniczne i asynchroniczne.
Uwaga
Model wywoływania asynchronicznego sterowany zdarzeniami nie jest obsługiwany w przypadku korzystania z klasy ChannelFactory<TChannel>. Aby uzyskać informacje na temat wykonywania wywołań asynchronicznych przy użyciu metody ChannelFactory<TChannel>, zobacz Instrukcje: wywoływanie operacji asynchronicznie przy użyciu fabryki kanałów.
Procedura
Aby asynchronicznie wywoływać operacje usługi WCF
Uruchom narzędzie ServiceModel Metadata Tool (Svcutil.exe) z
/async
opcjami polecenia i/tcv:Version35
, jak pokazano w poniższym poleceniu.svcutil /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples http://localhost:8000/servicemodelsamples/service/mex /a /tcv:Version35
Spowoduje to wygenerowanie oprócz synchronicznych i standardowych operacji asynchronicznych opartych na delegatach, klasy klienta programu WCF zawierającej:
Dwie
<operationName>``Async
operacje do użycia z podejściem asynchronicznym opartym na zdarzeniach. Na przykład: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); }
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
Operacja zakończyła zdarzenia formularza
<operationName>``Completed
do użycia z podejściem asynchronicznym opartym na zdarzeniach. Na przykład:public event System.EventHandler<AddCompletedEventArgs> AddCompleted;
Public Event AddCompleted As System.EventHandler(Of AddCompletedEventArgs)
System.EventArgs typy dla każdej operacji (formularza
<operationName>``CompletedEventArgs
) do użycia z podejściem asynchronicznym opartym na zdarzeniach. Na przykład:[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])); } } }
<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
W aplikacji wywołującej utwórz metodę wywołania zwrotnego, która ma zostać wywołana po zakończeniu operacji asynchronicznej, jak pokazano w poniższym przykładowym kodzie.
// Asynchronous callbacks for displaying results. static void AddCallback(object sender, AddCompletedEventArgs e) { Console.WriteLine("Add Result: {0}", e.Result); }
' 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
Przed wywołaniem operacji użyj nowego typu ogólnego System.EventHandler<TEventArgs> typu
<operationName>``EventArgs
, aby dodać metodę obsługi (utworzoną w poprzednim kroku) do<operationName>``Completed
zdarzenia. Następnie wywołaj metodę<operationName>``Async
. Na przykład:// 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);
' 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)
Przykład
Uwaga
Wytyczne dotyczące projektowania dla modelu asynchronicznego opartego na zdarzeniach stwierdzają, że jeśli zwracana jest więcej niż jedna wartość, jedna wartość jest zwracana jako Result
właściwość, a pozostałe są zwracane jako właściwości obiektu EventArgs . Jednym z tych wyników jest to, że jeśli klient importuje metadane przy użyciu opcji polecenia asynchronicznego opartego na zdarzeniach, a operacja zwraca więcej niż jedną wartość, obiekt domyślny EventArgs zwraca jedną wartość jako Result
właściwość, a pozostałe są właściwościami EventArgs obiektu. Jeśli chcesz otrzymać obiekt komunikatu jako Result
właściwość i mieć zwrócone wartości jako właściwości tego obiektu, użyj /messageContract
opcji polecenia . Spowoduje to wygenerowanie podpisu zwracającego komunikat odpowiedzi jako Result
właściwość EventArgs obiektu. Wszystkie wewnętrzne wartości zwracane są właściwościami obiektu komunikatu odpowiedzi.
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);
}
}
}
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