Wie kann ich bis zum Abschluss von BackgroundWorker warten?
Beachten Sie die folgende Stück code:
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += OnAsyncOperationCompleted;
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
Nehmen wir nun an will ich warten, bis bw
Oberflächen arbeiten. Was ist der richtige Weg, dies zu tun?
Meine Lösung ist diese:
bool finished = false;
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += (sender, args) =>
{
OnAsyncOperationCompleted(sender, args);
finished = true;
});
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
int timeout = N;
while (!finished && timeout > 0)
{
Thread.Sleep(1000);
--timeout;
}
if (!finished)
{
throw new TimedoutException("bla bla bla");
}
Aber ich mag es nicht.
Ich habe als Ersatz die finished
Flagge mit einem Synchronisations-event, setzen Sie ihn in die RunWorkerCompleted
hf block auf später, statt der while-Schlaf-Schleife.
Ach, es ist falsch, denn der code kann ausgeführt werden in der WPF oder WindowsForm Synchronisation Zusammenhang, in dem Fall würde ich block den gleichen thread wie die RunWorkerCompleted
handler wird ausgeführt, und das ist eindeutig nicht sehr smart move.
Ich würde gerne wissen, die bessere Lösung.
Dank.
EDIT:
P. S.
- Der Beispielcode ist so künstlich, absichtlich zu klären, meine Frage. Ich bin mir durchaus bewusst das Abschluss-Rückruf und doch möchte ich wissen, wie zu warten bis zur Fertigstellung. Das ist meine Frage.
- Ich bin mir bewusst
Thread.Join
,Delegate.BeginInvoke
,ThreadPool.QueueUserWorkItem
usw... Die Frage ist speziell überBackgroundWorker
.
EDIT 2:
OK, ich denke, es wird viel einfacher, wenn ich erkläre, das Szenario.
Habe ich ein unit-test-Methode, die ruft einige asynchrone code, die wiederum letztlich greift ein BackgroundWorker
zu denen auch ich bin in der Lage, einen pass completion handler. Der gesamte code ist von mir, so dass ich ändern kann, die Umsetzung, wenn ich möchte.
Ich bin nicht, jedoch, ersetzen Sie die BackgroundWorker
, weil es verwendet automatisch die richtige Synchronisierung-Kontext, so dass, wenn der code aufgerufen wird, auf einen UI-thread der Fertigstellung callback wird aufgerufen, auf dem selben UI-thread, der ist sehr gut.
Jedenfalls ist es möglich, dass der unit-test-Methode trifft das Ende vor den BW seine Arbeit beendet hat, das ist nicht gut. Deshalb möchte ich warten, bis die BW abgeschlossen und würde gerne wissen, der beste Weg für Sie.
Gibt es mehr Teile, aber das Gesamtbild ist mehr oder weniger wie ich es gerade beschrieben habe.
AutoResetEvent.WaitAll(new[] {doneEvent1, doneEvent2})
while(!fertig...){...}
Lösung. So, die Lösung wird immer werfen die TimedoutException. Soweit ich sagen kann, es wird nur möglich sein, zu warten, bis die DoWork-Ereignishandler zu beenden, nicht das RunWorkerCompleted-Ereignishandler durch die Natur der BackgroundWorker-Klasse. Auch ist es unmöglich zu garantieren, dass Sie einen job begonnen haben, aber Sie dieses problem lösen könnte, mit einem timeout-Wert. InformationsquelleAutor der Frage mark | 2009-08-26
Du musst angemeldet sein, um einen Kommentar abzugeben.
Versuchen Sie es mit der AutoResetEvent-Klasse ermöglicht so:
Vorsicht: sollten Sie sicherstellen, dass
doneEvent.Set()
aufgerufen wird, egal was passiert. Auch möchten Sie vielleicht, um diedoneEvent.WaitOne()
mit einem argument die Angabe eines timeout-Zeit.Hinweis: Dieser code ist ziemlich genau eine Kopie der Fredrik Kalseth Antwort auf eine ähnliche Frage.
InformationsquelleAutor der Antwort JohannesH
Warten, bis der Arbeitsthread im hintergrund ausgeführt (einzelne oder mehrere) Folgendes tun:
Erstellen Sie eine Liste von Hintergrund-Arbeitnehmer haben Sie ein Programm erstellt:
Fügen Sie den background-worker in der Liste:
Verwenden Sie die folgende Funktion zu warten für alle Arbeitnehmer in der Liste:
InformationsquelleAutor der Antwort Azhar Khorasany
BackgroundWorker hat ein Abschluss-event. Anstatt zu warten, rufen Sie Ihren restlichen code Weg aus der Abschluss-handler.
InformationsquelleAutor der Antwort Jeff Wilcox
Diese Frage ist alt, aber ich glaube nicht, dass der Autor bekam die Antwort die er suchte.
Dies ist ein bisschen schmutzig, und es ist in vb.NET aber für mich funktioniert
InformationsquelleAutor der Antwort goughy000
VB.NET
Diese können Sie verwenden, um die Kette mehrerer Ereignisse. (sudo-code Folgen)
InformationsquelleAutor der Antwort Don
Überprüfung
backgrWorker.IsBusy
in der Schleife mitApplication.DoEvents()
ist nicht schön Weise.Stimme ich mit @JohannesH, sollte man definitiv nutzen AutoResetEvent als eine elegante Lösung. Aber nicht, indem Sie es in UI-Thread, es führt dazu, dass Haupt-thread blockiert, und es sollte kommen aus einem anderen hintergrund-worker-thread.
InformationsquelleAutor der Antwort KevinBui
nicht ganz sicher, was u bedeuten, indem Sie warten. Meinst du, Sie wollen etwas tun (durch die BW), nachdem das ist getan, Sie wollen etwas anderes tun?
Einsatz bw.RunWorkerCompleted wie Sie tun (verwenden Sie eine separate Funktion für die Lesbarkeit), und in dieser callback-Funktion haben Sie die nächsten Sachen.
Starten Sie einen timer, um zu überprüfen, ob die Arbeit nicht zu lange dauert.
In der OnDoWorkLoadChildren:
InformationsquelleAutor der Antwort RvdK
In OpenCV exists-Funktion WaitKey. Ir erlaubt, dieses Problem zu lösen, das in dieser Weise:
InformationsquelleAutor der Antwort csc
Ich war auch auf der Suche nach einer passenden Lösung. Ich löste die Wartezeit mit einer exklusiven Sperre. Der kritische Pfad in den code schreiben, um eine öffentliche container (hier die Konsole) und eine Erhöhung oder Verringerung der Beschäftigten. Kein thread sollte stören beim schreiben dieser variable, da sonst die Zählung nicht mehr garantiert.
InformationsquelleAutor der Antwort be981
Ich verwendet Aufgaben mit einem BackgroundWorker
Können Sie eine beliebige Anzahl von Aufgaben, und fügen Sie zu einer Liste von Aufgaben.
Die Arbeiter beginnen, wenn eine Aufgabe Hinzugefügt wird, neu zu starten, wenn eine Aufgabe Hinzugefügt wird, während der Arbeiter IsBusy, und Stoppt, sobald es gibt keine weiteren Aufgaben mehr.
Wird diese ermöglichen es Ihnen, ein update des GUI asynchron, so viel, wie Sie benötigen, ohne zu frieren.
Dieser funktioniert wie für mich.
Alles was Sie jetzt brauchen, ist eine neue Aufgabe erstellen, und fügen Sie es an die List<>. Es wird ausgeführt werden, indem die Arbeiter in der Reihenfolge in der Liste<>
InformationsquelleAutor der Antwort Beefjeff