TEvent: WaitFor abbrechen
-
Hallo,
Müßtest du den Event mit SetEvent nicht erst auslösen damit WaitFor reagieren kann?
-
Ich habs mal ausprobiert.
wenn du in deinem Thread vor dem WaitFor
pEvent->ResetEvent();und im Hauptprogramm nach der MessageBox
pEvent->SetEvent();schreibst geht das wie gewünscht.
PS:
Das pEvent.reset( NULL); solltest du rausschmeißen.
-
Es geht mir nicht darum, dass ich das Event auslöse. Das funzt. Es geht darum, dass ich das ganze Abbrechen möchte, ohne dass das Event eingetreten ist.
Und ich möchte auch nicht mit Timeout arbeiten. Lt. Hilfe müsste das ja auch irgendwie funzen.
-
Da WaitFor auf den Event wartet, wird dir wohl nichts übrigbleiben als ihn auszulösen. Wenn das automatisch gehen soll, kapsle den Event doch in eine Klasse und löse in deren Destruktor SetEvent aus.
-
Das hier funktioniert bei mir
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "syncobjs.hpp" #include <memory> #include <iostream> class EventWrapper { public: std::auto_ptr< TEvent> pEvent; EventWrapper() { pEvent.reset( new TEvent( NULL, //Standard-Sicherheitsattribute0 true, //manuelles Reset false, //signal beim Start nicht gesetzt "")); } ~EventWrapper() { pEvent->SetEvent(); pEvent.reset(NULL); } }; std::auto_ptr<EventWrapper> event; class Foo :public TThread { public: Foo() :TThread( false) { } virtual void __fastcall Execute(void) { event->pEvent->ResetEvent(); event->pEvent->WaitFor( INFINITE); //kein Timeout std::cout << "Event beendet"<<std::endl; //hier komm ich nie hin } }; int main() { event.reset( new EventWrapper); std::auto_ptr< Foo> pFoo( new Foo); MessageBox( NULL,"Warten","Warten", MB_OK); event.reset( NULL); return 0; } //---------------------------------------------------------------------------
-
Da WaitFor auf den Event wartet, wird dir wohl nichts übrigbleiben als ihn auszulösen. Wenn das automatisch gehen soll, kapsle den Event doch in eine Klasse und löse in deren Destruktor SetEvent aus.
Wenn das Event ausgelöst wird, nur wenn ich es abbrechen will, ist es aber doof, weil es wird ja nicht wirklich ausgelöst sondern ich möchte nur nicht weiter warten und es soll NICHT der Code ausgeführt werden, der ausgeführt werden würde, wenn das Event aufgetreten wäre.
Ok, ich kanns dann auch mit nem Timeout und nem Ausschaltflag lösen. Aber was meint denn dann die Doku, wann der Rückgabewert wrAbandoned ausgegeben wird?
WaitFor waits for a specified time period for the signal to be set, and returns one of the values from the following table:
Value Meaning
wrSignaled The signal of the event was set.
wrTimeout The specified time elapsed without the signal being set.
wrAbandoned The event object was destroyed before the timeout period elapsed.
-
WAIT_ABANDONED
0x00000080L The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled.
-
Ist es richtig, wenn ich das so verstehe:
Wenn der Thread, der das Mutex-Objekt erstellt hat (in diesem Fall der Hauptthread, der das TEvent-Objekt erstellt hat) beendet wird, ohne das Objekt freizugeben, dann wird das den wartenden Threads damit signalisiert.
Korrekt?
Dann ist die Borland-Hilfe aber wohl falsch, oder?Schade, es ist doch eigentlich kein ungewöhnlicher Anwendungsfall, dass man das Warten auch abbrechen möchte, wenn das Ereignis nicht passiert. In meinem Fall: das Programm beenden. Könnte ich eigentlich in einem Thread auf mehrere Ereignisse warten? Dann könnt ich ein 'TuWas' und ein 'HörAuf'-Ereignis haben. Oder dem Ereignis direkt nen Parameter mitgeben (anstatt ein globales Flag, auf das von mehreren Threads zugegriffen wird).
-
kartoffelsack schrieb:
Und ich möchte auch nicht mit Timeout arbeiten.
Wieso?
-
weil eine Zeile wie
while( wrSignaled == pEvent->WaitFor( INFINITE)) { //doTask } //Abbruchcodeeinfacher ist als mehrer Zeilen wie
while( true) { int signal = pEvent->WaitFor( 1000); if( wrSignaled = signal) { //doTask } else { break; } } //Abbruch-Codeund bei Version zwei der Abbruchcode immer erst nach einer Sekunde, im Schnitt also nach 500 ms erreicht wird.
Das natürlich nur unter der Voraussetzung, dass das Ding so gearbeitet hätte, wie ichs mir gedacht bzw. ich es aus der Doku verstanden hätte.
-
Sorry für die Formatierung. Kommt davon, wenn man sich nicht einlogged.
Hier nochmal:
while( wrSignaled == pEvent->WaitFor( INFINITE)) { //doTask } //Abbruchcodeversus
while( true) { int signal = pEvent->WaitFor( 1000); if( wrSignaled == signal) { //doTask } else { break; } } //Abbruch-Code
-
Ich hab das immer so gelöst, das ich "Abbruch"-Events in eine Liste mit den restlichen zu erwartenden Events gesetzt habe. So konnte ich unmittelbar abbrechen.
-
eine Liste mit den restlichen zu erwartenden Events
Das führt mich zu meiner obigen Frage zurück:
kann ich auf mehrere Ereignisse zugleich warten?
So irgendwie ...
while( wrSignaled == pEvent1->WaitFor( INFINITE) || wrSignaled == pEvent2->WaitFor( INFINITE))
-
Der vollständigkeit halber:
Auf mehrere Events warten geht nur mit WinAPI: MsgWaitForMultipleObjects