Асинхронная модель программирования (APM)
Асинхронная операция, использующая шаблон разработки IAsyncResult, реализуется в виде двух методов с именами BeginOperationName
и EndOperationName
, которые соответственно начинают и завершают асинхронную операцию OperationName. Например, класс FileStream предоставляет методы BeginRead и EndRead для асинхронного считывания байтов из файла. Эти методы реализуют асинхронную версию метода Read .
Примечание.
Начиная с версии .NET Framework 4 библиотека параллельных задач предоставляет новую модель для асинхронного и параллельного программирования. Дополнительные сведения см. в разделах Библиотека параллельных задач (TPL) и Асинхронный шаблон, основанный на задачах (TAP).)
После вызова метода BeginOperationName
приложение может продолжить выполнение инструкций в вызывающем потоке, пока асинхронная операция выполняется в другом потоке. Для каждого вызова метода BeginOperationName
приложение должно вызывать метод EndOperationName
, получающий результаты операции.
Начало асинхронной операции
Метод BeginOperationName
начинает асинхронную операцию OperationName и возвращает объект, реализующий интерфейс IAsyncResult. В объектахIAsyncResult хранятся сведения об асинхронных операциях. В таблице ниже приведены сведения об асинхронной операции.
Элемент | Description |
---|---|
AsyncState | Относящийся к необязательному приложению объект, содержащий сведения об асинхронной операции. |
AsyncWaitHandle | Объект WaitHandle , который можно использовать, чтобы заблокировать выполнение приложения до завершения асинхронной операции. |
CompletedSynchronously | Значение, показывающее, что асинхронная операция выполнена в потоке, который использовался для вызова метода BeginOperationName , а не в отдельном потоке ThreadPool. |
IsCompleted | Значение, показывающее, выполнена ли асинхронная операция. |
Метод BeginOperationName
принимает любые параметры, объявленные в сигнатуре синхронной версии метода, которые передаются по значению или по ссылке. Выходные параметры не входят в сигнатуру метода BeginOperationName
. В сигнатуру метода BeginOperationName
также входят два дополнительных параметра. Первый из них определяет делегат AsyncCallback , который ссылается на метод, вызываемый при завершении асинхронной операции. Вызывающий объект может указать значение null
(Nothing
в Visual Basic), если не нужно вызывать метод при завершении операции. Вторым дополнительным параметром является определяемый пользователем объект. Этот объект можно использовать для передачи сведений о состоянии, относящихся к приложению, в метод, который вызывается при завершении асинхронной операции. Если метод BeginOperationName
принимает дополнительные параметры, относящиеся к операции, например массив байт для хранения байт, считанных из файла, объект AsyncCallback и объект состояния приложения являются последними параметрами в сигнатуре метода BeginOperationName
.
BeginOperationName
немедленно возвращает управление в вызывающий поток. Если метод BeginOperationName
создает исключения, это происходит до запуска асинхронной операции. Если метод BeginOperationName
создает исключения, метод обратного вызова не вызывается.
Завершение асинхронной операции
Метод EndOperationName
завершает асинхронную операцию OperationName. Возвращаемое значение метода EndOperationName
имеет тот же тип, что и значение его синхронной версии, и определяется асинхронной операцией. Например, метод EndRead возвращает число байтов, считанных из потока FileStream , а метод EndGetHostByName возвращает объект IPHostEntry , содержащий сведения о сервере. Метод EndOperationName
принимает любые выходные параметры out и ref, объявленные в сигнатуре синхронной версии метода. В дополнение к параметрам из синхронного метода метод EndOperationName
также включает параметр IAsyncResult. Вызывающие объекты должны передавать экземпляр, возвращаемый соответствующим вызовом метода BeginOperationName
.
Если асинхронная операция, представленная объектом IAsyncResult, не завершилась к моменту вызова метода EndOperationName
, метод EndOperationName
блокирует выполнение вызывающего потока до момента завершения асинхронной операции. Исключения, создаваемые асинхронной операцией, возникают из метода EndOperationName
. Многократный вызов метода EndOperationName
с одним экземпляром IAsyncResult не определен. Аналогично, вызов метода EndOperationName
с объектом IAsyncResult, который не был возвращен соответствующим методом Begin, также имеет неопределенный эффект.
Примечание.
В случае реализации этих неопределенных сценариев рекомендуется вызывать исключение InvalidOperationException.
Примечание.
В случае реализации этого шаблона разработки необходимо уведомить вызывающий объект о завершении асинхронной операции, установив свойство IsCompleted в значение true, вызвав асинхронный метод обратного вызова (если он указан) и отправив сигнал AsyncWaitHandle.
Разработчики приложений имеют выбор способов доступа к результатам асинхронной операции. Правильный выбор зависит от того, содержит ли приложение инструкции, которые могут выполняться, пока не завершена операция. Если приложение не может выполнять дополнительную работу, пока не получены результаты асинхронной операции, его необходимо заблокировать до момента, когда станут доступны результаты. Чтобы заблокировать работу до завершения асинхронной операции, используйте один из описанных ниже способов.
Вызов метода
EndOperationName
из главного потока приложения блокирует выполнение приложения до завершения операции. Пример с демонстрацией этого способа см. в статье Блокировка выполнения приложения путем завершения асинхронной операции.Используйте свойство AsyncWaitHandle , чтобы заблокировать выполнение приложения до завершения одной или нескольких операций. Пример, демонстрирующий этот способ, см. в разделе Blocking Application Execution Using an AsyncWaitHandle.
В приложениях, которые не нужно блокировать до завершения асинхронной операции, можно использовать один из описанных ниже способов.
Можно запрашивать состояние выполнения операции, периодически проверяя свойство IsCompleted, а когда операция будет завершена, вызвать метод
EndOperationName
. Пример, демонстрирующий этот способ, см. в разделе Запрос состояния асинхронной операции.Используйте делегат AsyncCallback для указания метода, который должен вызываться при завершении операции. Пример, демонстрирующий этот способ, см. в разделе Использование делегата AsyncCallback для завершения асинхронной операции.