2009-07-30 11 views
6

Ich muss einen so genannten Worker-Thread informieren, um die Arbeit bei der nächsten verfügbaren Opportunity zu beenden. Derzeit bin ich mit etwas wie folgt aus:Optionen zum Unterbrechen eines Threads

public void Run() 
    { 
     while (!StopRequested) 
      DoWork(); 
    } 

Die Sorge, die ich habe ist, dass StopRequested auf einem anderen Thread auf True gesetzt wird. Ist das sicher? Ich weiß, dass ich einen Boolean nicht sperren kann. Vielleicht gibt es eine andere Möglichkeit, einem Thread mitzuteilen, dass ein Stopp erforderlich ist. Zum Beispiel würde ich gerne überprüfen Thread.CurrentThread.ThreadState == ThreadState.StopRequested, aber es ist nicht klar, wie ich den Thread-Status als solcher einstellen kann.

+0

Warum können Sie einen booleschen Wert nicht sperren? Es wird allgemein als gute Praxis angesehen, ein separates "Objekt" für irgendwelche Schlösser zu erzeugen. –

+0

Ich kann das Bool nicht sperren, weil es ein Werttyp ist - ich könnte ein sogenanntes Sync-Objekt für keinen anderen Zweck erzeugen, als es zu sperren, wenn ich das Bool-Flag bekomme/setze --- aber es scheint mir, dass es sperrt auf einem Bool sollte sicher sein, und zumindest Reed Copsey stimmt zu –

+0

Ja, um einen Bool zu sperren sollte sicher sein. Kooperative Stornierung. Der Backgroundworker unterstützt ein ähnliches Konzept, wenn es für die von Ihnen ausgeführte Aufgabe geeignet ist. –

Antwort

3

Dies ist ein besserer Ansatz als zu versuchen, den Thread einzustellen. Wenn Sie sich die Dokumentation für ThreadState ansehen, heißt es ausdrücklich, dass StopRequested nur für den internen Gebrauch gedacht ist.

Das Setzen eines Booleschen Wertes von einem anderen Thread ist eine sichere Operation. Sie sollten in diesem Fall nicht sperren müssen.

+0

Ich würde gerne mehr über diesen Ansatz lesen. Haben Sie Links zu ähnlichen Fragen, Papieren, Blogs? –

2

Verwenden Event-Objekt wird wahrscheinlich besser. Vor allem, wenn dein Thread blockiert. (Dann können Sie nach wie vor für den Fall, warten in dem blockierenden Anruf)

3

Sie möchten vielleicht mit einem BackgroundWorker aussehen, um die Arbeit für Sie zu tun, mit RunWorkerAsync() und Umgang mit dem worker.CancellationPending == true Fall während Ihrer Logik.

BackgroundWorker worker = new BackgroundWorker(); 
worker.WorkerSupportsCancellation = true; 
worker.DoWork += MyWorkFunction; 
worker.RunWorkerCompleted += MyWorkDoneSuccessfullyFunction; 
worker.RunWorkerAsync(); 

wäre eine andere Lösung ein flüchtiges Bool zu verwenden sein, um zu signalisieren, dass Sie aufhören müssen, die Sie überall in der Klasse einstellen könnte.

+0

e.Cancelled Erst nachdem die Arbeiter gestoppt wurden, meinen Beitrag unten – SwDevMan81

+0

@ SwDevMan81 sehen: Sie richtig sind, editierte dieser Kommentar.Eine korrekte Implementierung für DoWork finden Sie hier: http://msdn.microsoft.com/en-us/library/system.componentmodel.doworkeventargs.argument.aspx –

2

Sie könnten Thread.Abort() verwenden und die erforderliche Bereinigung in der DoWork() - Methode in einem finally-Block umbrechen.

0

Wenn Sie die BackgroundWorker verwenden, würde rufen Sie die CancelAsync Funktion des Background setzt die CancellationPending Eigenschaft auf True, das ist, was Sie in Ihrer Schleife aussehen:

public void Run(object sender, DoWorkEventArgs e) 
{  
    BackgroundWorker worker = sender as BackgroundWorker; 
    if(worker != null) 
    { 
     while (!worker.CancellationPending) 
     { 
     DoWork(); 
     } 
    } 
} 

Die oben wäre die DoWork Ereigniscode, der beim Ausführen der -Funktion aufgerufen wird.

1

Die Sorge, die ich habe ist, dass StopRequested auf einem anderen Thread auf True gesetzt wird. Ist das sicher?

Sie sollten sicherstellen, dass das Feld StopRequested das Schlüsselwort volatile hat. Aus diesem Grund siehe this other answer.

Verwandte Themen