Wie wollen Sie schließen eine Anwendung, wenn einige Waithandle in der Mitte eines Anrufs zu WaitOne ist?

StackOverflow https://stackoverflow.com/questions/3087683

Frage

Gibt es eine standardisierte Möglichkeit, eine Anwendung „sauber“ zu schließen, während einige WaitHandle Objekte in dem Zustand eines Stromsperr Aufruf WaitOne sein können?

Zum Beispiel kann ein Hintergrund-Thread sein, die zusammen in einem Verfahren wie diese dreht:

while (_request.WaitOne())
{
    try
    {
        _workItem.Invoke();
    }
    finally
    {
        OnWorkCompleted();
    }
}

Ich sehe keine offensichtliche Art und Weise von diesem Thread zu verfügen, ohne Thread.Abort Aufruf (was von dem, was ich verstehe, wird abgeraten). Der Aufruf Close auf dem _request Objekt (ein AutoResetEvent), jedoch wird eine Ausnahme werfen.

Zur Zeit der Faden, der diese Schleife läuft, hat seine IsBackground Eigenschaft auf true und so die Anwendung erscheint richtig zu schließen. Da jedoch WaitHandle Arbeitsgeräte IDisposable, ich bin nicht sicher, ob dies als koscher oder wenn das Objekt wirklich sollte, bevor die App Ausfahrten entsorgt werden.

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

War es hilfreich?

Lösung

Definieren Sie eine zusätzliche WaitHandle genannt _terminate, die eine Anforderung signalisiert, die Schleife zu beenden, und dann verwendet WaitHandle.WaitAny statt WaitHandle.WaitOne.

var handles = { _request, _terminate };
while (WaitHandle.WaitAny(handles) == 0)
{
  try
  {
    _workItem.Invoke();
  }
  finally
  {
    OnCompleteWork();
  }
}

Andere Tipps

Wenn ein Thread blockiert (unabhängig davon, was sie blockt auf) können Sie Thread.Interrupt() nennen dies die Ausnahme ThreadInterruptedException verursachen wird (ich glaube, es könnte ein wenig anders sein) Sie diese Ausnahme auf den Faden umgehen kann selbst und machen jede neccesary aufzuräumen.

Es ist erwähnenswert,, dass der Faden nur die ThreadInterruptedException werfen, wenn es blockiert, wenn es nicht blockiert wird es nicht bis zum nächsten versucht, Block geworfen werden.

Dies ist der „sichere“ Weg Threads zu beenden, was ich zu diesem Thema gelesen habe.

auch bemerkenswert: Wenn das Objekt implementiert sowohl IDisposable und ein finializer (was es wird, wenn es nicht verwalteten Ressourcen verwendet) der GC wird die Finalizerthread nennen, die normalerweise dispose nennt. Normalerweise ist dies nicht deterministisch. Allerdings können Sie ziemlich viel garantieren sie auf das Beenden der Anwendung aufgerufen. Nur unter ganz besonderen Umständen würden sie nicht. (A .net Umgebung termininating Ausnahme wie StackOverflowException geworfen wird)

Stellen Sie die IsBackground Eigenschaft true ... es sollte automatisch schließen, der Faden, wenn Ihre Anwendung endet.

Alternativ können Sie den Thread unterbrechen durch den Aufruf Thread.Interrupt und behandeln die ThreadInterruptedException . Eine weitere Idee ist _request.Set() anrufen und die while-Schleife ein flüchtiges Flag, um zu bestimmen machen zu überprüfen, ob die Anwendung endet oder wenn sie fortgesetzt werden sollten:

private volatile bool _running = true;
while(_request.WaitOne() && _running)
{
    //...
}

// somewhere else in the app
_running = false;
_request.Set();

ich denke, das Betriebssystem aufzuräumen nach dem Prozess abgeschlossen ist. Da Ihr Thread als IsBackground markiert die CLR wird den Prozess und alle Fäden innerhalb enden, so dass dies kein Problem ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top