Когда используется асинхронный ввод-вывод (или «перекрывающийся» ввод-вывод на жаргоне Win32), нам нужно иметь дело со структурой OVERLAPPED
и ее элементом hEvent
. Если функция ввода-вывода задержит операцию чтения или записи, мы получим код ошибки ERROR_IO_PENDING
, затем дождемся завершения асинхронной операции с функцией WaitForXxxEvent
, а затем вызовем GetOverlappedResult
.
Однако, если операция ввода-вывода завершится немедленно, мы не получим ERROR_IO_PENDING
, а при операции чтения наш буфер чтения будет заполнен немедленно. А как насчет OVERLAPPED::hEvent
члена? Будет ли он установлен в сигнальное состояние? Я не нашел четкого утверждения об этом.
Этот вопрос может показаться бессмысленным (зачем обрабатывать событие, если я знаю, что операция уже завершена?), однако у меня есть библиотека, которая имитирует перекрывающийся шаблон, и мне нужно точно такое же поведение.
Как указано edgar.holleis в его комментарий, Раймонд Чен объяснил это в своем блоге: http://blogs.msdn.com/b/oldnewthing/archive/2014/02/06/10497096.aspx
Если асинхронный ввод-вывод завершается синхронно, сигнализируется ли hEvent в структуре OVERLAPPED в любом случае?
да.
Когда ввод-вывод завершается (синхронно или асинхронно), о событии сигнализируется, и уведомления о состоянии завершения помещаются в очередь. Функцию
GetOverlappedResult/Ex
можно использовать для ожидания уже завершенного ввода-вывода; он просто вернется немедленно. Если вы спросите у HasOverlappedIoCompleted, завершился ли ввод-вывод и завершился ли ввод-вывод синхронно, он правильно сообщит: «Да, конечно, он завершен. Черт возьми, он завершен давным-давно!»Другими словами, вы можете логически рассматривать случай синхронного выполнения асинхронного запроса ввода-вывода, как если бы он был завершен асинхронно. Он просто завершается асинхронно, прежде чем вы даже моргнули.