2016-09-20 7 views
1

Сегодня я узнал, что я могу назвать CreateIoCompletionPort(), а затем передать возвращенное HANDLE в WaitForSingleObject():WaitForSingleObject() на порт завершения?

#include <Windows.h> 

int main() 
{ 
    HANDLE h = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0); 
    auto bRes = PostQueuedCompletionStatus(h, 1, 2, 0); 
    if (!bRes) { 
     abort(); 
    } 

    auto dwRes = WaitForSingleObject(h, INFINITE); 
    if (dwRes != WAIT_OBJECT_0){ 
     abort(); 
    } 

    LPOVERLAPPED pOvr; 
    DWORD cb; 
    ULONG_PTR key; 
    bRes = GetQueuedCompletionStatus(
     h, &cb, &key, &pOvr, INFINITE); // <-- returns 1, 2, nullptr 

    if (!bRes) { 
     abort(); 
    } 

    dwRes = WaitForSingleObject(h, INFINITE); // <-- blocks here 
    return 0; 
} 

Он работает, как ожидается, на моем Windows 10 коробки.

Является ли такое поведение известным или законным или документированным? Я ничего не смог найти.

+0

'dwRes = WaitForSingleObject (h, INFINITE); // <- блокирует здесь' - действительно блокируется? ты уверен ? просто интересно – RbMm

+0

Да. Сброс дампа в состоянии ожидания и исходный код здесь: https://1drv.ms/f/s!AtyOp6RRUTUTC2CAVzWdFrvZu6w –

+0

Да, в win10 действительно ждут заголовок диспетчера KQUEUE. но сказать в win8.1 - нет. – RbMm

ответ

3

Если вы читаете WaitForSingleObject() documentation, ввода/вывода Завершение Порт НЕ разрешенный тип ручки:

WaitForSingleObject функция может ждать следующих объектов:

  • Изменить уведомление
  • Вход в консоль
  • Событие
  • память уведомление ресурса
  • мьютекс
  • Процесс
  • Семафор
  • Thread
  • Waitable таймер

Ждать событие завершения, чтобы прибыть на порт, вы должны передать дескриптор до GetQueuedCompletionStatus() и блокировать его до тех пор, пока не произойдет событие или не произойдет тайм-аут.

#include <Windows.h> 

int main() 
{ 
    HANDLE h = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0); 
    auto bRes = PostQueuedCompletionStatus(h, 1, 2, 0); 
    if (!bRes) { 
     abort(); 
    } 

    LPOVERLAPPED pOvr; 
    DWORD cb; 
    ULONG_PTR key; 
    bRes = GetQueuedCompletionStatus(
     h, &cb, &key, &pOvr, INFINITE); // <-- returns 1, 2, nullptr 

    if (!bRes) { 
     abort(); 
    } 

    bRes = GetQueuedCompletionStatus(
     h, &cb, &key, &pOvr, INFINITE); // <-- blocks here 

    return 0; 
} 
+1

Спасибо за быстрый ответ :-) WaitForSingleObject() может также ждать файла, хотя он явно не упоминается в документации для WaitForSingleObject() (см. Https://blogs.msdn.microsoft.com/oldnewthing/20121012-00/?p=6343, " дескриптор файла является ожидаемым объектом "). Я полностью осведомлен о правильном использовании портов завершения.Интересно, является ли порт завершения также ожидаемым объектом. –

+0

В документации для ['GetOverlappedResult()'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms683209.aspx) упоминается, что файл, именованный канал и дескриптор устройства связи также но не обескураживает их ожидания. Но ничто в документации по портам ввода/вывода (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198.aspx) не говорит о том, что дескриптор порта ввода-вывода напрямую возвращается. Если что-то не задокументировано, не полагайтесь на него. –

1

Резюме:

  • не делают этого. См. Ответ Remy Lebeau и MSDN о том, как правильно использовать порты завершения.
  • такое злоупотребление портами завершения не только недокументировано, но и ненадежно. Поведение варьируется между сборками Windows 10.
  • порт завершения, вероятно, является законным объектом для ожидания в ядре, поскольку KQUEUE, который поддерживает порт завершения, имеет DISPATCHER_HEADER.