Как узнать, когда CancelIo () сделано? - PullRequest
1 голос
/ 13 октября 2010

CancelIo () должен отменить все ожидающие операции ввода-вывода, связанные с вызывающим потоком.По моему опыту, CancelIo () иногда также отменяет операции future I / O.Дано:

ReadFile(port, buffer, length, &bytesTransferred, overlapped);
  1. Если я вызову CancelIo(port) непосредственно перед чтением, GetQueuedCompletionStatus() будет блокироваться вечно, никогда не получая операцию чтения.
  2. Если я вызову CancelIo(port)сразу после чтения GetQueuedCompletionStatus() вернет 0 с GetLastError()==ERROR_OPERATION_ABORTED
  3. Если я вызову CancelIo(port) и нет ожидающих или последующих чтений, GetQueuedCompletionStatus() заблокируется навсегда.

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

PS: Глядя на http://osdir.com/ml/lib.boost.asio.user/2008-02/msg00074.html и http://www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/using.html, это звучит как CancelIo ()не совсем годен к употреблению.Должен клиент требует поддержки Windows XP.Какие у меня варианты?

ПРИМЕЧАНИЕ : я читаю с последовательного порта.

Ответы [ 4 ]

3 голосов
/ 17 октября 2010

CancelIo() работает отлично.Я неправильно понял мой код.

При дальнейшем исследовании выясняется, что код вызывал CancelIo(), за которым следует ReadFile() с таймаутом INFINITE.Порт завершения никогда не получал уведомление о прочтении, потому что удаленный конец никогда ничего не отправлял.Другими словами, CancelIo() не отменял последующие операции.

Я нашел некоторую открывающую документацию здесь :

Будьте осторожны при кодировании для асинхронного I/ O потому что система оставляет за собой право сделать операцию синхронной, если ей нужно .Поэтому лучше всего написать программу для правильной обработки операции ввода-вывода, которая может быть выполнена либо синхронно, либо асинхронно.Пример кода демонстрирует это соображение.

Оказывается, что драйверы устройств могут выбрать обработку асинхронной операции синхронно, если считываемые данные уже кэшируются драйвером устройства.После дальнейшего расследования я обнаружил, что когда CancelIo() вызывался до ReadFile(), иногда это приводило к тому, что последний возвращался синхронно.Я понятия не имею, почему порт завершения никогда не получал уведомление о ReadFile() после CancelIo(), но я больше не могу воспроизвести эту проблему.

Порт завершения сигнализируется независимо от того, является ли ReadFile() синхронным илиасинхронный.

2 голосов
/ 13 октября 2010

Ожидание (возможно, с нулевым таймаутом) overlapped.Handle. Будет установлено, будет ли операция завершена или отменена.

0 голосов
/ 13 октября 2010

Если вы уже используете перекрывающиеся операции, зачем вообще нужно отменять ввод-вывод?Вся концепция «отмены» операции ввода-вывода в полете действительно склонна к гонкам и полностью зависит от базового стека устройств, к которому вы пытаетесь записать;на самом деле единственный раз, когда вы захотите это сделать, - это разблокировать другой поток, который ожидает завершения этого ввода / вывода.

0 голосов
/ 13 октября 2010

Можно написать код асинхронного ввода-вывода без функции CancelIo.Вопрос зависит от сценария, который вы используете CancelIO.Допустим, вам нужно реализовать поток чтения файлов.Псевдокод потока:

for(;;)
{
    ReadFile(port, buffer, length, &bytesTransferred, overlapped); 
    WaitForMultipleObjects( overlapped event + stop event);

    if ( stop event is signaled )
       break;

    if (overlapped event is signaled )
        handle ReadFile results
}

Такой поток читает файл (сокет, порт и т. Д.), Используя перекрывающийся ввод-вывод.Большую часть времени он ожидает в строке WiatForMultipleObjects.Он просыпается при появлении новых данных или сообщении о событии остановки.Чтобы остановить этот поток, установите событие остановки из другого потока.CancelIO не используется.

...