Существует несколько способов, с помощью которых операции могут выполняться асинхронно в .NET. Поскольку вы не опубликовали никаких подробностей, я дам обзор наиболее распространенных шаблонов:
AsyncWaitHandle
Часто вы найдете (особенно в классах .NET Framework) пары методов с именами Begin
и End
(т.е. что-то вроде BeginReceive
и EndReceive
).
Вызов функции begin возвращает объект AsyncWaitHandle
, который можно использовать для синхронизации потоков, как обычный WaitHandle
(путем вызова WaitOne
или передачи его в статические функции WaitHandle.WaitAny
или WaitHandle.WaitAll
), затем передается в соответствующую функцию "end", чтобы получить возвращаемое значение функции (или, если оно произошло, сгенерировать возникшее исключение).
Если вы используете простое средство .NET для асинхронного вызова метода (создания делегата для функции и вызова BeginInvoke
и EndInvoke
), то вам следует использовать этот подход. Однако большинство API, которые имеют встроенную поддержку асинхронных операций, будут обрабатывать фактическую асинхронную вызывающую часть для вас, оставляя вас с правильно названными функциями BeginXXX
и EndXXX
, вместо того, чтобы заставлять вас создавать делегата самостоятельно.
Образец с использованием WaitHandle
:
IAsyncResult result = object.BeginOperation(args);
result.AsyncWaitHandle.WaitOne();
// that will cause the current thread to block until
// the operation completes. Obviously this isn't
// exactly how you'd ordinarily use an async method
// (since you're essentially forcing it to be
// synchronous this way)
returnValue = object.EndOperation(result);
Часто асинхронные методы связаны с событиями, как показано ниже.
События
Иногда вызов метода, который завершается асинхронно, вызывает событие после его завершения. Это также иногда используется в сочетании с подходом AsyncWaitHandle
для доставки уведомления о завершении процесса. Например, библиотеки MSMQ имеют функцию BeginReceive
и EndReceieve
для объекта очереди, а также событие ReceieveCompleted
. Когда событие вызывается, это означает, что затем может быть вызван EndReceive
, передав объект AsyncWaitHandle
, возвращенный вызовом BeginReceive
. чтобы получить фактическое сообщение, которое было получено.
В любом случае, вы присоединяетесь к событию и используете его, как и любое другое событие.
Пример использования AsyncWaitHandle
и событий :
(где-то в коде)
object.OperationComplete += object_OperationComplete;
(в другом месте) * 1 057 *
IAsyncResult result = object.BeginOperation(args);
// at this point, you can either wait for the event
// to fire, or use the WaitHandle approach as shown
// in the previous example
...
void objectOperationComplete(object sender, AsyncOperationEventArgs e)
{
returnValue = object.EndOperation(e.AsyncResult);
}
Как правило, они работают различными способами ... вы можете самостоятельно удерживать IAsyncResult
, возвращаемый операцией Begin, но большинство библиотек передают этот объект IAsyncResult
как свойство в свой конкретный класс EventArgs
.
Также обычно можно найти возвращаемое значение, присутствующее в качестве свойства в классе EventArgs
. Хотя использовать это значение можно, , если операция Begin вернула IAsyncResult
, всегда полезно вызывать соответствующую функцию End , даже если необходимые данные находятся в EventArgs
. Функция End также обычно используется для обнаружения исключений.
Callbacks
Обратный вызов (в .NET) - это делегат, который предоставляется асинхронной функции. Обратные вызовы используются не только в асинхронных функциях, но в этом контексте они, как правило, являются делегатами, которые вы предоставляете при вызове функции, которую она будет вызывать по завершении.
Обратные вызовы аналогичны событиям (в том смысле, что они оба основаны на делегатах), хотя между вызовами методов и предоставленными обратными вызовами существует большая взаимно-однозначная корреляция.
Пример использования обратного вызова :
object.BeginOperation(args, OperationComplete);
...
void OperationComplete(SomeObject results)
{
...
}