Когда я открываю и читаю файл в 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]
не только ждать результата, но
поэтому 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]
или реализовать его функционал самостоятельно?