Практическое руководство. Асинхронный вызов операций с использованием фабрики каналов
В этой теме описывается, каким образом клиент может асинхронно обратиться к операции службы при использовании клиентского приложения, основанного на ChannelFactory<TChannel>. (При вызове службы с помощью объекта System.ServiceModel.ClientBase<TChannel> можно использовать управляемую событиями модель асинхронных вызовов. Дополнительные сведения см. в статье "Практическое руководство. Асинхронно вызовы операций службы". Дополнительные сведения об асинхронной модели асинхронного вызова на основе событий см. в статье "Асинхронная модель на основе событий(EAP)".)
Служба в этом разделе реализует интерфейс ICalculator
. Клиент может асинхронно вызвать операции для этого интерфейса, это означает, что операции типа Add
разделяются на два метода, BeginAdd
и EndAdd
, первый из них инициирует вызов, а второй извлекает результат после завершения операции. Пример реализации операции асинхронно в службе см. в статье "Практическое руководство. Реализация асинхронной операции службы". Дополнительные сведения об синхронных и асинхронных операциях см. в разделе "Синхронные и асинхронные операции".
Процедура
Асинхронный вызов операций службы WCF
Запустите средство служебной программы метаданных ServiceModel (Svcutil.exe) с параметром
/async
, как показано в следующей команде.svcutil /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples http://localhost:8000/servicemodelsamples/service/mex /a
Результатом станет создание асинхронной версии клиента контракта службы для операции.
Создайте функцию обратного вызова, вызываемую после завершения асинхронной операции, как показано в следующем примере кода.
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
Чтобы асинхронно обратиться к операции службы, создайте клиент и вызовите
Begin[Operation]
(напримерBeginAdd
) и задайте функцию обратного вызова, как показано в следующем примере кода.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)
При выполнении функции обратного вызова клиент вызывает
End<operation>
(напримерEndAdd
), чтобы извлечь результат.
Пример
Служба, используемая с клиентским кодом, который применяется в предыдущей процедуре, реализует интерфейс ICalculator
, как показано в следующем коде. На стороне Add
Subtract
службы и операции контракта вызываются синхронно временем выполнения Windows Communication Foundation (WCF), даже если предыдущие шаги клиента вызываются асинхронно на клиенте. Операции Multiply
и Divide
используются для асинхронного вызова службы на стороне службы, даже если клиент вызывает их синхронно. В этом примере свойству AsyncPattern присваивается значение true
. Этот параметр свойства в сочетании с реализацией асинхронного шаблона платформа .NET Framework сообщает среде выполнения асинхронно вызывать операцию.
[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