2009-03-20 12 views
5

Given: ja wypełnić tablicę z uchwytów samochodowych imprez Reset i przekazać go do WaitForMultipleObjects z bWaitAll = False.Zachowanie WaitForMultipleObjects gdy wiele uchwyty sygnalizują jednocześnie

Od MSDN: "Gdy bWaitAll jest FALSE, ta funkcja sprawdza uchwyty w tablicy począwszy od indeksu 0, aż jeden z obiektów zostanie zasygnalizowany. Jeśli zostanie zasygnalizowanych wiele obiektów, funkcja zwróci indeks pierwszego uchwytu w tablicy, której obiekt został zasygnalizowany. "

Teraz, jeśli sygnał wielu obiektów otrzymam indeks pierwszego. Czy muszę pętli przez moją tablicę, aby sprawdzić, czy inni sygnalizowali?

Teraz mam pętlę, która znajduje się wzdłuż linii:

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

Odpowiedz

4

Teraz, jeśli sygnał wielu obiektów, otrzymam indeks pierwszego. Czy muszę mieć pętlę przez moją tablicę, aby sprawdzić, czy inni sygnalizowali?

Dlaczego po prostu nie wrócić do Wait()? jeśli zasygnalizuje to wiele obiektów, nadal będą sygnalizowane, gdy wrócisz do rundy. Oczywiście, jeśli masz bardzo szybko wystrzeliwujący pierwszy obiekt w tablicy obiektów oczekiwania, będzie głodować pozostałe; to, co robisz, zamawia twoje obiekty w macierzy obiektów oczekiwania przez częstotliwość wypalania, przy czym najmniejszy jest pierwszy.

BTW, gdzie używasz niekończąca się do(), można użyć Goto. Jeśli naprawdę nie opuszczasz pętli, bezwarunkowe goto najbardziej poprawnie wyraża twoje zamiary.

+0

To jest efektywnie używane rozwiązanie. Klucz, który musiałem wymyślić, brzmiał: "jeśli wiele obiektów zostanie zasygnalizowanych, nadal będą sygnalizowane, kiedy wrócisz". Jeśli nie muszę się martwić o głód, moje oryginalne rozwiązanie było w porządku. – Chris

+1

Tak. WaitForMultipleObjects() skanuje tablicę uchwytów od 0 i zwraca, gdy tylko znajdzie zasygnalizowany uchwyt. Tylko ten pierwszy znaleziony uchwyt jest resetowany do stanu nie sygnalizowanego; pozostałe są nietknięte. –

5

Tak. Jedną z opcji może być wykonanie WaitForSingleObject (uchwyt, 0) na każdym uchwycie, który natychmiast powróci i wskaże, czy są sygnalizowane, czy nie.

EDIT: Oto próbka Pseudokod za to, co mam na myśli:

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! 
     } 
    } 
} 
+0

Tak to zrobić po WaitForMultipleObjects zadzwonić –

+0

Dzięki za sugestię, dodał Pseudokod to pokazać. – Michael

+0

Problem z tą odpowiedzią polega na tym, że zasadniczo włączono bWaitAll przy pomocy tego obiektu WaitForSingleObject. Nie chcę czekać na wszystkie uchwyty, po prostu obsługuj te, które sygnalizują. – Chris

3

Innym rozwiązaniem może masz jest użycie RegisterWaitForSingleObject. Idea polega na tym, że sygnalizowany jest sygnalizowany stan zdarzenia w tablicy pomocniczej z funkcji wywołania zwrotnego, a następnie sygnalizujemy zdarzenie główne, które jest używane do wybudzenia głównego wątku (który wywołuje obiekt WaitForSingleObject w zdarzeniu głównym).

Oczywiście trzeba by zadbać o to, że wtórne tablica była chroniona przed dostępem przez głównego wątku, ale to działa.

Powiązane problemy