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?
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.
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)
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:
Tags und Links c# multithreading idisposable shutdown waithandle