HasOverlappedIoCompleted()
не работает с асинхронным вводом / выводом, начатым с ReadFileEx()
и WriteFileEx()
. Фрагмент кода внизу демонстрирует это. В этом примере ReadFileEx()
читает из канала, который не имеет ввода, поэтому чтение не будет завершено. Но HasOverlappedIoCompleted()
возвращает TRUE. Если я изменяю вызов на перекрывающийся ReadFile()
, то HasOverlappedIoCompleted()
возвращает FALSE, как и ожидалось.
Мой вопрос: как я могу узнать, завершился ли перекрывающийся запрос ввода-вывода с обратным вызовом, не полагаясь на сам обратный вызов? В моем приложении APC, возможно, был поставлен в очередь, но не обязательно должен еще запускаться, потому что приложение еще не ожидало в состоянии оповещения.
Спасибо.
(Примечание. GetOverlappedResult () не помогает - он также возвращает TRUE.)
Немного больше предыстории: в примере я использую ReadFileEx()
, потому что проблему легко продемонстрировать. В моем приложении я звоню WriteFileEx()
неоднократно на экземпляре канала. Если предыдущий WriteFileEx()
еще не завершен, я должен отбросить сообщение, а не отправлять его (у меня не должно быть более одной ожидающей записи в одном и том же экземпляре канала), но если предыдущий WriteFileEx()
завершил , затем я должен запустить следующий, , даже если обратный вызов для завершения еще не запущен .
Редактировать: описание сценария проблемы
- Поток переходит в состояние оповещения (с одним прочитанным APC в очереди).
- Начинается чтение APC: он ставит в очередь функцию WriteFileEx () и устанавливает флаг ожидания записи. Затем он ставит в очередь ReadFileEx ().
- Основной поток начинает работу (без предупреждения).
- Чтение в очереди завершено.
- Запись в очереди завершается (после чтения).
- Основной поток переходит в состояние оповещения.
- APC для чтения является первым в очереди, поэтому запускается первым: он просматривает флаг 'отложенной записи' и, поскольку он все еще установлен, сбрасывает запись. На самом деле, хотя WriteFileEx () завершил , он просто еще не вызвал свой APC, потому что ReadFileEx () завершился первым.
Вместо того, чтобы тестировать мой пользовательский флаг 'ожидающих записи', я хочу выяснить в ОС, действительно ли WriteFileEx () завершена, даже если APC еще не запущен.
#include <Windows.h>
#include <stdio.h>
#include <assert.h>
VOID CALLBACK readComplete(DWORD err, DWORD bytes, LPOVERLAPPED ovlp)
{
}
int main(int argc, char *argv[])
{
HANDLE hServer;
OVERLAPPED serverOvlp = { 0 };
HANDLE hClient;
DWORD bytes;
BYTE buffer[16];
BOOL result;
hServer = CreateNamedPipe("\\\\.\\pipe\\testpipe", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
serverOvlp.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ConnectNamedPipe(hServer, &serverOvlp);
assert(GetLastError() == ERROR_IO_PENDING);
hClient = CreateFile("\\\\.\\pipe\\testpipe", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
GetOverlappedResult(hServer, &serverOvlp, &bytes, TRUE);
/* Server starts an overlapped read */
// result = ReadFile(hServer, buffer, sizeof(buffer), &bytes, &serverOvlp);
result = ReadFileEx(hServer, buffer, sizeof(buffer), &serverOvlp, readComplete);
if (HasOverlappedIoCompleted(&serverOvlp))
{
puts("Completed");
}
else
{
puts("Not completed");
}
return EXIT_SUCCESS;
}