Асинхронное взаимодействие
Асинхронный образец демонстрирует, как клиент может асинхронно получить доступ к операции службы и как служба может асинхронно реализовать свои операции. Данный образец основан на образце Образец для начала работы, реализующем службу калькулятора. Использование синхронного или асинхронного вызова является локальным решением и не влияет на отправленные по сети сообщения. Несмотря на то что служба реализует некоторые синхронные операции, клиент может получить доступ к операциям службы асинхронно. Несмотря на то что клиент вызывает службу синхронно, служба может реализовывать некоторые операции асинхронно.
Примечание |
---|
Процедура настройки и инструкции по построению для этого образца приведены в конце этого раздела. |
В этом образце клиентом является консольное приложение (EXE), а служба является резидентной в консольном приложении (EXE).
Служба реализует интерфейс ICalculator
. Клиент может вызвать операции в данном интерфейсе асинхронно. Это означает, что такие операции, как Add
, теперь имеют BeginAdd
и EndAdd
.
Примечание |
---|
Дополнительные сведения об асинхронном шаблоне см. в документации по .NET Framework. |
Клиент имеет созданный код, который поддерживает данные асинхронные операции. Клиент был создан путем запуска средства Служебное средство ServiceModel Metadata Utility Tool (Svcutil.exe) с параметром /a (async)
, как указано ниже.
svcutil /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples https://localhost:8000/servicemodelsamples/service/mex /a /tcv:Version35
Клиентская асинхронная версия контракта службы для операции Add
подобна следующему коду.
[System.ServiceModel.ServiceContractAttribute(Namespace=
"http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
[System.ServiceModel.OperationContractAttribute(
AsyncPattern=true)]
System.IAsyncResult BeginAdd(double n1, double n2,
System.AsyncCallback callback, object asyncState);
double EndAdd(System.IAsyncResult result);
...
}
Если с параметром /tcv:Version35
указан параметр /async
, для вызова службы созданный тип клиента реализует асинхронную модель на основе событий. Дополнительные сведения см. в разделе Обзор асинхронной модели на основе событий. Чтобы асинхронно получить доступ к операции службы, приложение добавляет обработчик событий в событие [Operation]Completed
на клиенте и затем вызывает метод [Operation]Async
(например, AddAsync
), как показано в следующем примере кода.
// Create a client.
CalculatorClient client = new CalculatorClient();
// BeginAdd.
double value1 = 100.00D;
double value2 = 15.99D;
client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback);
client.AddAsync(value1, value2);
В данном образце клиент асинхронно начинает две операции: Add
и Subtract
.
При выполнении функции обратного вызова клиент, чтобы извлечь результат, получает доступ к свойству Result
входного параметра [Operation]CompletedEventArgs
.
static void AddCallback(object sender, AddCompletedEventArgs e)
{
Console.WriteLine("Add Result: {0}", e.Result);
}
Все асинхронное поведение локально для клиента и не влияет на сообщения, отправленные с клиента, или обработанные службой. Как правило, причиной использования данного шаблона в приложении пользовательского интерфейса (UI) является сохранение потока пользовательского интерфейса для обновления экрана. Данный шаблон также применяется, если служба действует как клиент и нужно освободить поток обработки сообщения от вызовов к другим службам. В следующем разделе демонстрируется, как сделать операцию службы асинхронной.
Служба реализует интерфейс ICalculator
, как показано в следующем коде.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginMultiply(double n1, double n2,
AsyncCallback callback, object state);
double EndMultiply(IAsyncResult ar);
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginDivide(double n1, double n2,
AsyncCallback callback, object state);
double EndDivide(IAsyncResult ar);
}
Первые две операции контракта вызываются синхронно с помощью выполнения Windows Communication Foundation (WCF). Последние две пары операций используются для асинхронного вызова службы. В этом образце свойству AsyncPattern присваивается значение true. Этот параметр свойства в сочетании с реализацией асинхронного шаблона .NET Framework сообщает среде выполнения о необходимости асинхронного вызова операции.
Обычно причиной использования данного шаблона в реализации службы является необходимость освобождения потоков обработки сообщений при выполнении длительных операций ввода и вывода, таких как получение доступа к диску, получение доступа к базе данных или вызов другой службы. В данном образце демонстрируется способ переноса операций ввода и вывода с помощью реализации IAsyncResult. Базовый класс для реализации класса MathAsyncResult
может быть повторно использован для записи собственных реализаций IAsyncResult
.
Примечание |
---|
Во избежание упорядочивающего поведения, которое возможно при использовании сеансовой привязки, в данном образце используются PerCall и Multiple. Для установки контекста безопасности привязка wsHttpBinding использует сеанс по умолчанию. Это не влияет на асинхронность обработки сообщения клиентом или службой, но учитывает временные параметры реакций и дает возможность клиенту наблюдать за параллельными обратными вызовами, а не за последовательными. |
При выполнении образца запросы и отклики операции отображаются в окне консоли клиента. Запросы Add
и Subtract
не блокируются, поскольку они вызываются асинхронно. Затем блокируются операции Multiply
и Divide
, а их результаты отображаются одновременно с прекращением работы запросов. В итоге результаты операций Add
и Subtract
отображаются тогда же, когда их результаты возвращаются обратно клиенту. Операция sleep
используется в реализации службы операций Add
и Subtract
для демонстрации асинхронных обратных вызовов клиенту.
Add(100,15.99)
Subtract(145,76.54)
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Add Result: 115.99
Subtract Result: 68.46
ИД потоков используются в службе для демонстрации того, что синхронные вызовы, такие как Add
и Subtract
, обрабатываются в одном потоке. Асинхронные вызовы, такие как Multiply
и Divide
, включают более одного потока. Вывод службы имеет следующий вид.
Received Add Synchronously on ThreadID 11: Sleeping for 3 seconds
Asynchronous call: BeginMultiply on ThreadID 12
Received Subtract Synchronously on ThreadID 12: Sleeping for 3 seconds
IO thread for * operation on ThreadID 13
EndMultiply called on ThreadID 14
Asynchronous call: BeginDivide on ThreadID 14
IO thread for / operation on ThreadID 13
EndDivide called on ThreadID 14
Returning Add Result on ThreadID 11
Returning Subtract Result on ThreadID 12
Асинхронная модель .NET Framework может быть использована или на клиенте, или в службе, или и там и там. Как показывает этот образец, обе стороны не зависят друг от друга.
Настройка, построение и выполнение образца
Убедитесь, что выполнены процедуры, описанные в разделе Процедура однократной настройки образцов Windows Communication Foundation.
Чтобы выполнить построение версии решения для языка C# или Visual Basic .NET, следуйте инструкциям раздела Построение образцов Windows Communication Foundation.
Чтобы выполнить образец на одном или нескольких компьютерах, следуйте инструкциям в разделе Running the Windows Communication Foundation Samples.
Примечание |
---|
Образцы уже могут быть установлены на компьютере. Перед продолжением проверьте следующий каталог (по умолчанию).
<диск_установки>:\WF_WCF_Samples
Если этот каталог не существует, перейдите на страницу Образцы Windows Communication Foundation (WCF) и Windows Workflow Foundation (WF) для .NET Framework 4, чтобы загрузить все образцы Windows Communication Foundation (WCF) и WF. Этот образец расположен в следующем каталоге.
<диск_установки>:\WF_WCF_Samples\WCF\Basic\Contract\Service\Asynchronous
|