GetOverlappedResult (bWait = TRUE) vs WaitForSingleObject () для перекрывающихся ввода / вывода

Когда я открываю и читаю файл в OVERLAPPED образом на Win32 api, у меня есть несколько способов завершить запрос ввода-вывода, включая ожидание дескриптора файла (или события в перекрываемой структуре), используя

  • WaitForSingleObject
  • GetOverlappedResult с bWait = TRUE

Обе функции, похоже, имеют одинаковый эффект: stream остановлен до тех пор, пока не будет сигнализирована ReadFile или событие, а это означает, что данные помещаются в буфер, предоставленный ReadFile .

Итак, в чем разница? Зачем мне нужен GetOverlappedResult ?

Вы могли бы использовать любой из них, но на самом деле это не «правильный» способ сделать это. вы должны прикрепить дескриптор к порту завершения ввода-вывода, а затем подождать порт завершения. Таким образом, у вас есть один пул streamов, обслуживающий множество событий ввода-вывода, так как вы можете присоединить несколько дескрипторов к порту завершения. Я рекомендую прочитать « Проектирование приложений для высокой производительности» .

Я полностью согласен с ответом Ремуса Русану . вместо этого создайте собственный IOCP и пул streamов, которые будут прослушиваться в этом IOCP , вы можете использовать или BindIoCompletionCallback или CreateThreadpoolIo (начать с Vista) – в этом случае система самостоятельно создаст IOCP и пул streamов, которые будут прослушиваться в этом IOCP, и когда некоторые завершение операции – вызов вашего обратного вызова. это очень упрощает код vs собственного пула iocp / thread ( собственный пул iocp / thread действительно, я думаю, имеет смысл реализовать только тогда, когда у вас очень большое количество операций ввода-вывода (например, сокет io на стороне сервера) и нужна специальная оптимизация для работы )

тем не мение

Итак, в чем разница? Зачем мне нужен GetOverlappedResult

как вы можете видеть GetOverlappedResult[Ex] не только ждать результата, но

  • вернитесь к вам NumberOfBytesTransferred, если операция завершена.
  • если операция завершена с ошибкой NTSTATUS – преобразуйте ее в ошибку win32 и установите последнюю ошибку
  • если операция еще не выполнена, и вы хотите подождать – выберите wait на hFile или hEvent

поэтому GetOverlappedResult[Ex] делает гораздо больше, чем просто вызвать WaitForSingleObject

однако не очень сложно реализовать этот API самостоятельно. например

 BOOL WINAPI MyGetOverlappedResult( _In_ HANDLE hFile, _In_ LPOVERLAPPED lpOverlapped, _Out_ LPDWORD lpNumberOfBytesTransferred, _In_ BOOL bWait ) { if ((NTSTATUS)lpOverlapped->Internal == STATUS_PENDING) { if (!bWait) { SetLastError(ERROR_IO_INCOMPLETE); return FALSE; } if (lpOverlapped->hEvent) { hFile = lpOverlapped->hEvent; } if (WaitForSingleObject(hFile, INFINITE) != WAIT_OBJECT_0) { return FALSE; } } else { MemoryBarrier(); } *lpNumberOfBytesTransferred = (ULONG)lpOverlapped->InternalHigh; NTSTATUS status = (NTSTATUS)lpOverlapped->Internal; if (status) { RtlNtStatusToDosError(status); } return NT_SUCCESS(status); } 

так что лучше: использовать GetOverlappedResult[Ex] или реализовать его функционал самостоятельно?