Wie schließt man eine Anwendung, wenn sich WaitHandle mitten in einem Aufruf von WaitOne befindet?

8

Gibt es eine Standardmethode, um eine Anwendung "sauber" zu schließen, während sich einige WaitHandle -Objekte im Zustand eines aktuellen blockierenden Aufrufs von WaitOne befinden?

Zum Beispiel gibt es möglicherweise einen Hintergrund-Thread, der sich in einer Methode wie dieser dreht:

%Vor%

Ich sehe keinen offensichtlichen Weg, diesen Thread zu entfernen, ohne Thread.Abort aufzurufen (was von dem, was ich verstehe, entmutigt wird). Der Aufruf von Close für das Objekt _request (ein AutoResetEvent ) löst jedoch eine Ausnahme aus.

Gegenwärtig wird für den Thread, der diese Schleife ausführt, die IsBackground -Eigenschaft auf true festgelegt, sodass die Anwendung angezeigt wird , um ordnungsgemäß geschlossen zu werden. Da WaitHandle jedoch IDisposable implementiert, bin ich nicht sicher, ob dies als Koscher betrachtet wird oder ob dieses Objekt wirklich entfernt werden sollte, bevor die App beendet wird.

Ist das ein schlechtes Design? Wenn nicht, wie wird dieses Szenario typischerweise behandelt?

    
Dan Tao 21.06.2010, 19:11
quelle

4 Antworten

8

Definieren Sie ein zusätzliches WaitHandle namens _terminate , das eine Anfrage zum Beenden der Schleife signalisiert und dann WaitHandle.WaitAny anstelle von WaitHandle.WaitOne verwendet.

%Vor%     
Brian Gideon 21.06.2010, 19:37
quelle
1

Wenn ein Thread blockiert (unabhängig davon, auf was er blockiert), können Sie Thread.Interrupt() aufrufen. Dies wird die Ausnahme ThreadInterruptedException verursachen (ich glaube, es könnte etwas anders sein). Sie können diese Ausnahme im Thread selbst behandeln und tun Sie etwas aufzuräumen.

Es ist erwähnenswert, dass der Thread nur das ThreadInterruptedException wirft, wenn es blockiert wird, wenn es nicht blockiert wird, wird es erst geworfen, wenn es das nächste Mal versucht, es zu blockieren.

Dies ist der "sichere" Weg, Threads von dem zu beenden, was ich zu diesem Thema gelesen habe.

auch erwähnenswert: Wenn das Objekt sowohl IDisposable als auch einen Finializer implementiert (was es tun wird, wenn es nicht verwaltete Ressourcen verwendet), ruft der GC den Finalizer auf, der normalerweise dispose aufruft. Normalerweise ist dies nicht deterministisch. Sie können jedoch ziemlich garantieren, dass sie beim Beenden der Anwendung aufgerufen werden. Nur unter ganz besonderen Umständen würden sie nicht. (Eine .net-Environment-Beendigungsausnahme wie StackOverflowException wird ausgelöst)

    
Sekhat 21.06.2010 19:18
quelle
1

Setzen Sie die Eigenschaft IsBackground auf true ... Sie sollte den Thread automatisch schließen, wenn Ihre App beendet wird.

Alternativ können Sie den Thread unterbrechen, indem Sie Thread.Interrupt und behandeln Sie die ThreadInterruptedException . Eine andere Idee ist, _request.Set() aufzurufen und die while-Schleife ein flüchtiges Flag überprüfen zu lassen, um festzustellen, ob die Anwendung geschlossen wird oder fortgesetzt werden sollte:

%Vor%     
Kiril 21.06.2010 19:14
quelle
0

Ich denke, dass das Betriebssystem nach dem Prozess bereinigt wird. Da Ihr Thread als IsBackground markiert ist, beendet die CLR den Prozess und alle darin enthaltenen Threads. Dies ist also kein Problem.

    
Grzenio 21.06.2010 19:19
quelle