Чтение канала асинхронно с использованием ReadFile - PullRequest
0 голосов
/ 02 июля 2018

Я думаю, что мне нужно кое-что прояснить, как читать из именованного канала и заставить его немедленно возвращаться, данные или нет. Я вижу, что ReadFile завершается с ошибкой, как и ожидалось, но GetLastError возвращает либо ERROR_IO_PENDING, либо ERROR_PIPE_NOT_CONNECTED, и это происходит до истечения времени ожидания моего окружающего кода. Я получаю эти ошибки ДАЖЕ ЧЕРЕЗ ДАННЫЕ В ФАКТЕ ПРИБЫЛИ. Я знаю это, проверяя мой буфер чтения и видя, что я ожидаю. И труба продолжает работать. Я подозреваю, что не правильно использую перекрывающуюся структуру, я просто устанавливаю все поля на ноль. Мой код выглядит так:

gPipe = CreateFile(gPipename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
pMode = PIPE_READMODE_MESSAGE; 
bret = SetNamedPipeHandleState(gPipe, &pMode, NULL, NULL);

OVERLAPPED ol;
memset(&ol, 0, sizeof(OVERLAPPED));

// the following inside a loop that times out after a period
bret = ReadFile(gPipe, &tmostat, sizeof(TMO64STAT), NULL, &ol);
if (bret) break;
err = GetLastError();
// seeing err == ERROR_IO_PENDING or ERROR_PIPE_NOT_CONNECTED

Так что я могу делать то, что хочу, игнорируя ошибки и проверяя поступившие данные, но меня это беспокоит. Есть идеи, почему у меня такое поведение?

1 Ответ

0 голосов
/ 02 июля 2018

Windows OVERLAPPED I / O не работает как флаг неблокирования в других ОС (например, в Linux ближайший эквивалент - aio_*() API, а не FIONBIO)

С OVERLAPPED I / O операция не завершилась, она продолжается в фоновом режиме. Но вы никогда не проверяете это ... вы просто пытаетесь снова. Есть очередь ожидающих операций, вы всегда начинаете новые, никогда не проверяете старые.

Заполните поле hEvent в структуре OVERLAPPED и используйте его, чтобы определить, когда операция завершится. Затем вызовите GetOverlappedResult(), чтобы узнать количество фактически переданных байтов.

Еще одно важное замечание - ОС владеет структурой OVERLAPPED и буфером до завершения операции, вы должны убедиться, что они остаются действительными и не освобождать их или использовать их для любых других операций, пока вы не подтвердите, что первая операция завершено.


Обратите внимание, что существует фактический неблокирующий режим для каналов Win32, но Microsoft настоятельно рекомендует не использовать его:

Режим ожидания без блокировки поддерживается для совместимости с Microsoft LAN Manager версии 2.0. Этот режим не должен использоваться для достижения перекрывающихся входов и выходов (I / O) с именованными каналами. Вместо этого следует использовать перекрывающийся ввод-вывод, поскольку он позволяет выполнять трудоемкие операции в фоновом режиме после возврата из функции.

...