Как убить ожидающую операцию APM

Если у вас есть ожидающая операция, например

stream.BeginRead(_buffer, 0, _buffer.Length, _asyncCallbackRead, this);

и вы закрываете потокового провайдера, например

serialPort.Close();

Вы неудивительно, что вы вызываете исключение.

Есть ли предпочтительный метод, с помощью которого можно отменить ожидающую операцию APM перед закрытием порта?

Ответ Колби - не тот ответ, на который я надеялся, но он, по крайней мере, закрывает бесплодную дорогу в расследовании.

К счастью, я нашел решение.

Для каждого потока я поддерживаю различную информацию о состоянии в классеDeviceSession, У этого класса есть методReadStream обеспечение реализации дляAsyncCallback это обрабатывает входящие данные.

Обратите внимание, что_asyncCallbackRead и каждая другая переменная, начинающаяся с подчеркивания, является закрытым членом класса, назначенным в конструкторе DeviceSession.

Конструктор также обеспечивает начальный вызов_stream.BeginRead.

void ReadStream(IAsyncResult ar)
{
  if (IsOpen) 
    try
    {
      DevicePacket packet;
      int cbRead = _stream.EndRead(ar);
      _endOfValidData += cbRead;
      while ((packet = GetPacket()) != null)
        CommandStrategy.Process(this, packet);
      _stream.BeginRead(_buffer, _endOfValidData, 
        _buffer.Length - _endOfValidData, 
        _asyncCallbackRead, null);
    }
    catch (Exception ex)
    {
      Trace.TraceError("{0}\r\n{1}", ex.Message, ex.StackTrace);
      _restart(_streamProvider, _deviceId);
    }
}

Обратите внимание, что я не удосужился установитьar.AsyncState, Поскольку делегат обратного вызова относится к методу конкретного экземпляра DeviceSession, подробная и строго типизированная контекстная информация (содержащаяся в элементах этого экземпляра DeviceSession)автоматически в рамках. Это точка наличия объекта сеанса.

Возвращаясь к теме прерывания слушателя, закрытие потокового провайдера вызывает обратный вызов, но попытка вызвать EndRead приводит кIOException.

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

Хитрость заключается в том, чтобы добавить больше контекста (IsOpen) кDeviceSession чтобы указать, открыт ли сеанс или был закрыт, и использовать его для плавного завершения окончательного неудачного выполненияReadStream.

ЕслиIsOpen являетсяtrue затемIOException представляет собой сбой, нуждающийся в восстановлении. ЕслиIsOpen являетсяfalse отказ был умышленно вызван, и никаких действий не требуется.

Ответы на вопрос(2)

[Вдохновленный главой о APM в CLR Рихтера через C #, я решил посмотреть, какие полезности есть у SO по этому вопросу, и нашел этот вопрос. что у Питера был отличный вопрос, и он провел небольшое исследование - это результат]

Джеффри Рихтер в CLR через C # (глава 27) обсуждает свой класс AsyncEnumerator, который (предположительно) снимает большую часть боли с программирования APM. Одна из особенностей этого класса (часть его в свободном доступеPower Threading Libary) - возможность отмены асинхронных операций.

Класс можно скачать по ссылке выше. Страница также содержит ссылку на Yahoo Group Richter, настроенную для предоставления ограниченной поддержки библиотеки.

Он представляет библиотеку в следующих статьях MSDN:

Упрощенный APM с помощью AsyncEnumerator
Дополнительные функции AsyncEnumerator

Решение Вопроса

болочку, которая порождает поток, и использовать примитивы синхронизации, такие как события, для подачи запроса на отмену.

НТН

Колби Африка

Ваш ответ на вопрос