PDA

Visualizza la versione completa : [C++] Come conoscere se un evento è settato


misterx
03-08-2011, 21:38
usando le funzioni sotto indicate, mi chiedevo come conoscere se un evento è ancora settato o meno.
Mi è capitato e mi capita, di richiamare una dopo l'altra

ResetEvent(hEvent1);
SetEvent(hEvent2);

in questo ordine in quanto ResetEvent(hEvent1) mette a "dormire" un thread e SetEvent(hEvent2) sveglia il secondo thread, ma accade a volte in maniera randomica che entrambi i thread si mettono nella condizione

WaiteForSingleObject(HEvent1, INFINITE);
.....
....
WaiteForSingleObject(HEvent2, INFINITE);


Per evitare questo stallo mi sonon chiesto se esiste un modo per controllare se entrambi i thread sono in attesa in modo da sbloccarne uno dei due, ma esiste il metodo?

Una cosa del tipo

if(WaiteForSingleObject(HEvent2, INFINITE) && WaiteForSingleObject(HEvent1, INFINITE))
SetEvent(hEvent1);

avrebbe senso?

grazie 1000

oregon
03-08-2011, 23:02
Penso di non avere compreso pienamente il problema ... e l'ho riletto più volte ... sarà la stanchezza ...

XAlbeX
03-08-2011, 23:51
Neanche io ho capito tanto bene..

Tu vuoi sapere se un evento è settato senza aspettare?
Se è così, basta che gli passi 0 come parametro dwMilliseconds.


MSDN
If dwMilliseconds is zero, the function does not enter a wait state if the object is not signaled; it always returns immediately.

ad esempio


// Se entrambi gli eventi non sono settati...
if (
WaitForSingleObject(hEvent1,0) == WAIT_TIMEOUT &&
WaitForSingleObject(hEvent2,0) == WAIT_TIMEOUT
)
SetEvent (hEvent1);

misterx
04-08-2011, 07:43
Originariamente inviato da XAlbeX
Neanche io ho capito tanto bene..

Tu vuoi sapere se un evento è settato senza aspettare?
Se è così, basta che gli passi 0 come parametro dwMilliseconds.



ad esempio


// Se entrambi gli eventi non sono settati...
if (
WaitForSingleObject(hEvent1,0) == WAIT_TIMEOUT &&
WaitForSingleObject(hEvent2,0) == WAIT_TIMEOUT
)
SetEvent (hEvent1);



si se si ècapito quello che intendevo, scusate ma ero stanco anch'io e non sempre mi riesce di esporre con la dovuta chiarezza, faccio un esempio:

//thread1
WaitForSingleObject(hEvent1,INFINITE);
if(capita qualcosa)
SetEvent(hEvent2); //risveglio il secondo thread
ResetEvent(hEvent1); // metto in attesa il primo thread


//thread2
WaitForSingleObject(hEvent2,INFINITE);
eseguo il compito assegnatomi
SetEvent(hEvent1); //risveglio il primo thread
ResetEvent(hEvent2); // metto in attesa il secondo thread

quando eseguo il thread2 a volte in modo casuale mi ritrovo coi due thread bloccati in WaitForSingleObject() e questo non riesco a spiegarmelo; sarà la solita schedulazione di windows che forse trascorso un certo tempo il SetEvent(hEvent1); non viene più sentito ed entrambi i thread attendono all'infinito.

Per tale motivo chiedevo se c'era un modo di testare la condizione appena esposta e cioè, se trovo entrambi i thread in Wait.....() risveglio uno dei due.


Vale ancora il tuo esempio?

ciao

linoma
04-08-2011, 09:02
Forse usando degli eventi non autoresettanti riesci, ma molto dipende da cm hai organizzato il tuo programma, se si verificano delle situazioni di deadlock molto probabilmente i solo eventi nn bastano.

oregon
04-08-2011, 09:33
Windows non c'entra ... è l'architettura del tuo programma che è anomala.

Se gestisci l'avvio e la sospensione di due thread uno con l'altro in quel modo, stai creando tutte le condizioni classiche per un deadlock. come ti ha detto linoma.

Devi ripensare l'algoritmo con cui deve funzionare il tuo programma.

misterx
04-08-2011, 09:35
Originariamente inviato da linoma
Forse usando degli eventi non autoresettanti riesci, ma molto dipende da cm hai organizzato il tuo programma, se si verificano delle situazioni di deadlock molto probabilmente i solo eventi nn bastano.

il programma è strutturato come nell'esempio citato appena sopra.

Facendo delle prove ho notato che si sblocca ma chiaramente per essere tranquillo ho applicato la medesima soluzione ad entrambi i thread.



//thread1
WaitForSingleObject(hEvent1,INFINITE);
if(capita qualcosa)
SetEvent(hEvent2); //risveglio il secondo thread
ResetEvent(hEvent1); // metto in attesa il primo thread
if (
WaitForSingleObject(hEvent1,0) == WAIT_TIMEOUT &&
WaitForSingleObject(hEvent2,0) == WAIT_TIMEOUT
)
SetEvent (hEvent1);


//thread2
WaitForSingleObject(hEvent2,INFINITE);
eseguo il compito assegnatomi
SetEvent(hEvent1); //risveglio il primo thread
ResetEvent(hEvent2); // metto in attesa il secondo thread
if (
WaitForSingleObject(hEvent1,0) == WAIT_TIMEOUT &&
WaitForSingleObject(hEvent2,0) == WAIT_TIMEOUT
)
SetEvent (hEvent2);


Stranamente se inserisco una attesa nel thread 2 di 5 millisecondi in questo modo

//thread2
WaitForSingleObject(hEvent2,INFINITE);
eseguo il compito assegnatomi
SetEvent(hEvent1); //risveglio il primo thread

Sleep(5);

ResetEvent(hEvent2); // metto in attesa il secondo thread

Sembra che lo stallo non si verifichi mai!


gli eventi NON sono autoresettanti (oregon ne sa qualcosa in quanto ne avevamo già discusso)

hEvent1 = CreateEvent ( NULL , true , false , "Event 10234" );
hEvent2 = CreateEvent ( NULL , true , false , "Event 11234" );

Loading