Betrachten wir ein hypothetische Methode eines Objekts, das Material für Sie tut:Wie warten, bis ein BackgroundWorker abbricht?
public class DoesStuff
{
BackgroundWorker _worker = new BackgroundWorker();
...
public void CancelDoingStuff()
{
_worker.CancelAsync();
//todo: Figure out a way to wait for BackgroundWorker to be cancelled.
}
}
Wie kann man für einen Background warten zu tun?
In der Vergangenheit Menschen haben versucht:
while (_worker.IsBusy)
{
Sleep(100);
}
Aber this deadlocks, weil IsBusy
erst gelöscht, nachdem das RunWorkerCompleted
Ereignis behandelt wird, und das Ereignis nicht behandelt bekommen kann, bis die Anwendung im Leerlauf geht . Die Anwendung wird nicht inaktiv, bis der Worker fertig ist. (Außerdem ist es eine geschäftige Schleife - ekelhaft.)
andere vorgeschlagen haben add kludging es in:
while (_worker.IsBusy)
{
Application.DoEvents();
}
Das Problem mit diesem ist, dass es Application.DoEvents()
Nachrichten verursacht zur Zeit in der Warteschlange verarbeitet werden, die Ursache Re-entrancy-Probleme (.NET ist nicht einspringend).
Ich würde hoffen, dass irgendeine Lösung beteiligt Ereignissynchronisationsobjekte zu verwenden, wobei der Code wartet für eine Veranstaltung -, dass der RunWorkerCompleted
Event-Handler-Sets des Arbeitnehmers. Etwas wie:
Event _workerDoneEvent = new WaitHandle();
public void CancelDoingStuff()
{
_worker.CancelAsync();
_workerDoneEvent.WaitOne();
}
private void RunWorkerCompletedEventHandler(sender object, RunWorkerCompletedEventArgs e)
{
_workerDoneEvent.SetEvent();
}
Aber ich bin zurück in die Sackgasse: Der Event-Handler kann nicht ausgeführt werden, bis die Anwendung im Leerlauf geht, und die Anwendung wird nicht untätig gehen, weil es für ein Ereignis wartet.
Also, wie können Sie warten, bis ein BackgroundWorker fertig ist?
aktualisieren scheinen Menschen mit dieser Frage verwechselt werden. Sie scheinen zu glauben, dass ich als den Background verwenden werden:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += MyWork;
worker.RunWorkerAsync();
WaitForWorkerToFinish(worker);
Das heißt nicht es, das ist nicht, was ich tue, und das ist nicht was hier gefragt wird. Wenn dies der Fall wäre, hätte es keinen Sinn, einen Hintergrundarbeiter zu verwenden.
Das funktioniert gut, bis auf einen Fehler. Das Ereignis muss im Status "not set" erstellt werden: private AutoResetEvent _resetEvent = new AutoResetEvent (false); –
Also, wenn Sie Ihren Beitrag bearbeiten und dieses Update machen könnten, wird es eine Antwort für das Alter sein! –
Guter Fang; behoben :) –