Иллюстрированный самоучитель по Architecture .NET

Маршализация, прикладные области и контексты. Асинхронное программирование. Асинхронные шаблоны проектирования .lAsyncResult.

По умолчанию объекты копируются из одной прикладной области в другую (передаются по значению). В разделе "Удаленный доступ" показано, как происходит передача по ссылке между прикладными областями. Это гарантирует изоляцию кода одной прикладной области от кода другой.

Объекты передаются по ссылке между контекстами. Это позволяет общеязыковой среде времени выполнения CLR удовлетворять требования (например, синхронизацию или транзакции) различных объектов, независимо от того, находится ли клиент объекта в той же самой прикладной области или в другой.

Поскольку большинство объектов не являются производными от ContextBoundObject, они могут постоянно храниться в одном контексте или перемещаться при необходимости из одного контекста в другой. При этом потоки могут пересекать границы прикладных областей или контекстов в пределах одного и того же процесса Win32.

Асинхронное программирование

.NET поддерживает шаблон проектирования для асинхронного программирования. Этот шаблон используется во многих местах .NET (включая операции ввода-вывода, как было отмечено ранее, и как будет более подробно показано в главе 11 "Web-службы"). Асинхронное программирование может вызывать метод без блокирования вызывающей программы метода. С точки зрения клиента использовать асинхронную модель проще, чем потоки. Однако она предоставляет гораздо меньше возможностей управления синхронизацией по сравнению с использованием синхронизирующих объектов. Поэтому разработчики классов, вероятно, сочтут, что использовать потоки намного легче.

Асинхронные шаблоны проектирования

Такой шаблон проектирования состоит из двух частей: набора методов и интерфейса lAsyncResult. Методы шаблона имеют следующий вид:

lAsyncResult *BeginXXX(
[InputParams], AsyncCallback *cb, Object *AsyncObject)
[ReturnValue] EndXXX([OutputParams], lAsyncResult *ar);

В шаблоне проектирования XXX обозначает реальный метод, который вызывается асинхронно (например, BeginRead/EndRead для класса System::IO::FileStream). BeginXXX должен принимать те же входные параметры, что и его синхронный аналог (in, in/out и ref), а также параметры AsyncCallback и AsyncObject. В сигнатуре EndXXX должны присутствовать все выходные параметры (ref, out, in/out) синхронной версии. Этот метод должен возвратить любой объект или значение, которое возвращает синхронная версия данного метода. Он должен также иметь параметр lAsyncResult. Может быть предусмотрен и метод Cancelxxx, если в нем имеется необходимость.

AsyncCallback – делегат, который представляет функцию обратного вызова.

public _delegate void AsyncCallback(lAsyncResult *ar);

AsyncObject доступен из lAsyncResult. Реализовано это так, что в функции обратного вызова можно определить, во время какого асинхронного чтения был сделан обратный вызов.

Каркас использует данный шаблон таким образом, чтобы синхронный метод Read (Чтение) класса FileStream можно было использовать асинхронно. Ниже приведено описание синхронного метода FileStream::Read:

int Read(// Чтение
_in unsigned char* array _gc[],
int offset, int count);
// int смещение, int счетчик);

А вот асинхронная версия, используемая в шаблоне проектирования:

lAsyncResult *BeginRead(
_in unsigned char* array _gc[],
int offset, int numBytes,
// смещение,
AsyncCallback *userCallback,
Object *stateObject); // Объект
int EndRead(lAsyncResult *asyncResult);

Любое исключение, которое запускается в BeginXXX, должно быть запущено до начала выполнения асинхронных операций. Каждое исключение, связанное с асинхронными операциями, должно быть запущено из метода EndXXX.

lAsyncResult

Метод BeginXXX (такой как BeginRead) возвращает lAsyncResult. Следующий интерфейс содержит четыре элемента:

public _gc _interface lAsyncResult
// сборщик мусора – интерфейс lAsyncResult
{
public:
bool get_IsCompleted(); // логический (булев)
bool get_CompletedSynchronously();// логический (булев)
WaitHandle* get_AsyncWaitHandle();
Object* get_AsyncState(); }

Полю get_IsCompleted будет присвоено значение true (истина) после обработки вызова сервером. Клиент может уничтожить все ресурсы после того, как get_IsCompleted получит значение true (истина). Полю get_CompletedSynchronously будет присвоено значение true (истина), если BeginXXX заканчивается синхронно. Чаще всего это поле игнорируется и по умолчанию его значение устанавливается равным false (ложь). Обычно клиент даже не знает, выполняется ли метод BeginXXX синхронно или асинхронно. Если асинхронная операция не закончена, метод EndXXX блокируется до завершения выполнения операции.

Метод get_AsyncWaitHandle возвращает дескриптор WaitHandle, который можно использовать в целях синхронизации. Ранее мы видели, что этот дескриптор способен получать сигналы, так что клиент может организовать ожидание с его помощью. Поскольку можно указать период времени ожидания, то не нужно блокироваться навсегда в случае, если операция еще не закончена.

Объект get_AsyncState – последний параметр в вызове метода BeginXXX. Он позволяет дифференцировать процессы чтения в асинхронном режиме при обратном вызове.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.