Win32: ReadFileEx () для блоков STD_IN_HANDLE, почему?

Я пытаюсь использовать Win32 API для создания подпотока, который читает из STD_INPUT_HANDLE и помещает байты, которые он читает, в сокет. Поскольку я хочу иметь возможность безопасно завершать этот поток, когда пора выходить, я использую ReadFileEx () и перекрывающийся ввод-вывод вместо простого старого блокирующего ReadFile (). Идея состоит в том, что мой поток будет ждать в WaitForSingleObject () вместо ReadFile (), и когда основной поток хочет, чтобы подчиненный поток ушел, он подаст сигнал на этот объект, подчиненный поток проснется и выйдет, а затем основной поток может продолжить свою последовательность завершения работы.

Моя проблема заключается в следующем: несмотря на документацию, в которой говорится, что ReadFileEx () является асинхронным и, следовательно, никогда не блокируется ... мой подчиненный поток по-прежнему блокируется внутри ReadFileEx (). (Я вставил printf в цикл обработки событий, чтобы проверить, где он блокировался). Из-за этого мой основной поток не может закрыть подчиненный поток, и поэтому основная программа никогда не завершается.

Я что-то не так делаю, или ReadFileEx () предназначен для блокировки при чтении из стандартного ввода? Если последнее, каково решение проблемы отключения потока? Функция входа подчиненного потока ниже для вашего личного ...

[... in the main thread, before the slave thread is spawned...]
_stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
_wakeupSignal = CreateEvent(0, false, false, 0);
[...]

VOID WINAPI CompletedReadRoutine(DWORD dwErr, DWORD cbBytesRead, LPOVERLAPPED lpOverLap)
{
   printf("CompletedReadRoutine dwErr=%li cbBytesRead=%li overlap=%p\n", dwErr, cbBytesRead, lpOverLap);
}

void StdinDataIO :: IOThreadEntry()
{
   char buf[4096];
   OVERLAPPED olap;
   bool keepGoing = true;
   bool overlappedReadPending = false;
   while(keepGoing)
   {
      if (overlappedReadPending)
      {
         DWORD waitResult = WaitForSingleObjectEx(_wakeupSignal, INFINITE, true);
         switch(waitResult)
         {
            case WAIT_IO_COMPLETION:
            {
               overlappedReadPending = false;
               DWORD numBytesRead;
               if ((GetOverlappedResult(_stdinHandle, &olap, &numBytesRead, true) == false)||(SendData(_slaveSocket, buf, numBytesRead, true) != numBytesRead)) keepGoing = false;
            }
            break;

            default:
               keepGoing = false;
            break;
         }
      }
      else
      {
         memset(&olap, 0, sizeof(olap));
         if (ReadFileEx(_stdinHandle, buf, sizeof(buf), &olap, CompletedReadRoutine)) overlappedReadPending = true;
                                                                                 else keepGoing = false;
      }
   }
   if (overlappedReadPending) CancelIo(_stdinHandle);
   _slaveSocket.Reset();  // this alerts the main thread that we are gone
}
4 голоса | спросил Jeremy Friesner 22 AM00000080000001031 2009, 08:43:10

1 ответ


0

Из документации ReadFileEx описывающий тип дескриптора файла, который вы можете передать:

  

Этот дескриптор файла должен быть   создан с помощью FILE_FLAG_OVERLAPPED   флаг и должен иметь GENERIC_READ   право доступа.

В противном случае ReadFileEx заблокируется, когда вы вызываете его с дескриптором, который не открывается с помощью FILE_FLAG_OVERLAPPED

Вы также можете вызвать WaitForSingleObject или другую функцию синхронизации для дескриптора, возвращенного GetStdHandle и вызовите _kbhit или другую комбинацию обработки событий консоли, если вы хотите убедиться, что есть вход доступен.

ответил MSN 22 AM00000080000005231 2009, 08:52:52

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132