2010-05-17 11 views
15

ich eine Anwendung, die einige Hintergrundaufgabe hat in einem separaten Thread (Netzwerk & Lesen hören). Es scheint jedoch, dass das Thema nicht/Abgebrochen Abgebrochen wird, wenn ich die Anwendung (klicken Sie auf „x“ -Taste auf titlebar) schließen. Ist das, weil die Haupt-Thread-Routine ist while(true) {...}? Was ist die Lösung hier? Ich war auf der Suche für einige „Unterbrechung“ Flag für das Thema als Bedingung für „while“ Schleife, aber haben keine gefunden.Thema nicht abbrechen nicht auf Anwendung Schließen

Antwort

21

Der einfachste Weg ist es, die IsBackground Eigenschaft des Fadens auf true zu setzen. Dadurch wird verhindert, dass die Anwendung geöffnet bleibt. Eine Anwendung wird beendet, wenn alle Nicht-Hintergrund-Threads beendet werden.

Ein kontrollierterer Weg, den Thread zu stoppen, besteht darin, ihm eine Nachricht zu schicken, um sauber herunterzufahren und sicherzustellen, dass er beendet ist, bevor der Haupt-Thread beendet wird. Eine Methode, die ich nicht empfehlen würde, ist Thread.Abort zu rufen. Dies hat eine Reihe von Problemen, von denen eine ist, dass es nicht garantiert ist, den Thread zu beenden. Aus der Dokumentation:

Aufruf dieser Methode normalerweise beendet den Thread.

Schwerpunkt meiner.

+1

+1 auf die Nachrichtenmethode.'while (stayAlive)' anstelle von 'true' ist viel sauberer, selbst wenn es möglicherweise ein paar Sekunden mehr dauert, bis die Schleife aufräumt. – user7116

0

Nun, statt while(true), vielleicht sollten Sie:

while(appIsRunning) 
{ 
} 

Und bei der Abschlussveranstaltung für das Formular,

appIsRunning = false; 
thread.Join(2000); 

wo die letzte Zeile gerade ist, um sicherzustellen, Sie warten, der Faden sauber zu beenden. Es gibt viele andere Möglichkeiten, ein Ende zu einem Thread zu erzwingen, aber das Problem ist nur da: Sie wollen nicht zwingen Dinge, Sie wollen, dass sie so natürlich wie möglich passieren.

Nach dem verbinden, können Sie den Status des Threads überprüfen, um zu sehen, ob es beendet ist. Wenn dies nicht der Fall ist, dann (und nur dann) erzwingen Sie seinen Abschluss mit einem Abbruch, und vielleicht Ihren Benutzer benachrichtigen (oder schreiben Sie einen Protokolleintrag), dass etwas nicht so beendet ist, wie es sollte.

+0

Ja, aber denken Sie daran, 'volatile' oder' lock' oder eine andere Methode der Synchronisation zu verwenden. –

+0

@Mark: könnte hier völlig falsch sein, aber da der untergeordnete Thread nur liest und der Haupt-Thread nur schreibt, gibt es eine Chance für einen Bug? –

+1

Ohne Synchronisierung ist nicht garantiert, dass eine Änderung von appIsRunning von einem Thread im anderen Thread sichtbar ist. Sie können mehr hier lesen: http://timl.net/2009/03/volatile-memory.html –

1

Sie konnten die while (true) Schleife

void DoWork() { 
    while(!ShouldIQuitManualResetEvent.WaitOne(0)) { 
     // do something 
    } 
    IDidQuitManualResetEvent.Set() 
} 

Ein bisschen mehr anmutig, kurz von den Bezeichnernamen verbessern.

3

Sie können jederzeit die Ausgabe erzwingen:

class Program 
{ 
    public static void Main() 
    { 
     // ... do stuff 
     Environment.Exit(Environment.ExitCode); 
    } 
} 

Der bessere Ansatz ist es, die Thread.IsBackground Eigenschaft auf true gesetzt als Mark bereits erwähnt.

0

Sie können Ihren Thread als Start:

ThreadPool.QueueUserWorkItem(DoStuff, input) 

Und es wird automatisch mit der Anwendung schließt Abbruch sein.