Поведение WaitForMultipleObjects, когда несколько дескрипторов сигнализируют одновременно - PullRequest
5 голосов
/ 20 марта 2009

Дано: я заполняю массив дескрипторов событиями автоматического сброса и передаю его в WaitForMultipleObjects с bWaitAll = FALSE.

Из MSDN: «Когда bWaitAll имеет значение FALSE, эта функция проверяет дескрипторы в массиве в порядке, начиная с индекса 0, пока не будет сигнализирован один из объектов. Если несколько объектов становятся сигнальными, функция возвращает индекс первого дескриптора в массиве, объект которого был сигнализирован. ”

Итак, теперь, если несколько объектов сигнализируют, я получу индекс первого. Должен ли я пройти через мой массив, чтобы увидеть, есть ли какие-либо другие сигналы?

Прямо сейчас у меня есть цикл, который выглядит следующим образом:

For ( ; ; )
{
WaitForMultipleObjects(…)
If  (not failed)
     Process object that called. 
     Remove the handle that signaled from the array.
     Compact the arrary.
}

Ответы [ 4 ]

5 голосов
/ 25 марта 2009

Итак, теперь, если несколько объектов подадут сигнал, я получу индекс первого. Должен ли я цикл хотя мой массив, чтобы увидеть, если другие сигнализировали?

Почему бы просто не вернуться обратно в Wait ()? если несколько объектов сигнализируют, они все равно будут сигнализироваться, когда вы вернетесь. Конечно, если у вас есть очень быстрый запуск первого объекта в массиве ожидающих объектов, остальные будут голодать; то, что вы делаете, это упорядочиваете ваши объекты в массиве ожидающих объектов по частоте срабатывания, причем наименьшее частое - первое.

Кстати, где вы используете бесконечный for (), вы можете использовать goto. Если вы действительно не выходите из цикла, безусловный переход наиболее правильно выражает ваше намерение.

5 голосов
/ 20 марта 2009

Да. В качестве альтернативы вы можете использовать WaitForSingleObject (handle, 0) для каждого дескриптора, который немедленно вернется и укажет, сигнализированы они или нет.

РЕДАКТИРОВАТЬ: Вот образец псевдокода для того, что я имею в виду:

ret = WaitForMultipleObjects()
if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + (count))
{
    firstSignaled = ret - WAIT_OBJECT_0;

    // handles[firstSignaled] guaranteed signalled!!

    for (i = firstSignaled + 1; i < count; i++)
    {
        if (WaitForSingleObject(handles[i], 0) == WAIT_OBJECT_0)
        {
           // handles[i] Signaled!
        }
    }
}
3 голосов
/ 22 марта 2009

Еще одна опция, которую вы можете использовать, это использовать RegisterWaitForSingleObject. Идея состоит в том, что вы помечаете сигнальное состояние события во вторичном массиве из функции обратного вызова, а затем сигнализируете о главном событии, которое используется для пробуждения вашего основного потока (которое вызывает WaitForSingleObject для основного события).

Очевидно, что вы должны позаботиться о том, чтобы вторичный массив был защищен от доступа основным потоком, но он будет работать.

0 голосов
/ 26 июля 2016

Будет сброшено только событие автосброса, завершившее ожидание (чей индекс возвращается). Если время ожидания истекло, никакие события не будут сброшены.

ср https://blogs.msdn.microsoft.com/oldnewthing/20150409-00/?p=44273

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...