Warum ist BackgroundWorker immer beschäftigt?

8

Ich habe etwas merkwürdiges in meinem Hintergrundarbeiter in meiner WPF-Anwendung bemerkt.

Was ich gerade erreichen möchte, ist zu warten, bis das BW fertig ist, um einen anderen Thread zu starten.

Überprüfen Sie den folgenden Code:

%Vor%

Bitte beachten Sie, dass ich einen Dispatcher.Invoke hinzugefügt habe, um zu warten, bis der bw nicht beschäftigt ist, aber die ganze Zeit besetzt ist, wenn ich ihn aufrufe und niemals das RunWorkerAsyncCompleted -Ereignis auslöst. Obwohl ,, wenn ich diese Zeile entferne, FIRES das Ereignis und es ist wirklich seltsam, dass.

Wie kann ich warten bis der BW fertig ist?

    
Darf Zon 21.01.2013, 00:34
quelle

4 Antworten

25

Dies wird "Deadlock" genannt, ein sehr häufiges Threading-Problem. Die BGW kann nicht damit aufhören, beschäftigt zu sein, bis das RunWorkerCompleted-Ereignis ausgeführt wird. Dieses Ereignis wird im Hauptthread Ihrer App ausgeführt. Es kann nur ausgeführt werden, wenn Ihr Hauptthread nicht mit etwas anderem beschäftigt ist. Es muss inaktiv sein und innerhalb der Dispatcher-Schleife laufen.

Aber Ihr Haupt-Thread ist nicht im Leerlauf, er bleibt in der while () Schleife hängen und wartet darauf, dass IsBusy false zurückgibt. Daher kann das Ereignis nie ausgeführt werden, da der Hauptthread gerade nicht damit beschäftigt ist, auf die Beendigung der BGW zu warten. Die BGW kann nicht abgeschlossen werden, da der Hauptthread niemals inaktiviert wird. "Tödliche Umarmung", auch bekannt als Deadlock.

Sie müssen das anders machen, Sie können nicht warten. Sagen Sie, indem Sie eine andere Instanz von BGW erstellen. Oder lassen Sie diesen Code nicht laufen, bis das RWC-Ereignis ausgelöst wird. Oder indem Sie ein Flag setzen, das vom RunWorkerCompleted-Event-Handler getestet wurde, der dann die BGW erneut starten kann.

    
Hans Passant 21.01.2013 01:25
quelle
2

Ich bin mir nicht sicher, ob ich das richtig verstanden habe, aber ich denke, dass Sie versuchen, den BackgroundWorker neu zu starten (wenn er also beschäftigt ist, hören Sie erst auf und starten ihn dann erneut), Wenn dies das ist, was Sie wollen, versuchen Sie Folgendes:

Deklarieren Sie diesen Delegierten irgendwo in Ihrer Klasse:

%Vor%

und verwenden Sie diesen Code, um Ihren BackgroundWorker neu zu starten:

%Vor%     
someone else 21.01.2013 06:58
quelle
2

Der Deadlock tritt auf, weil der "Haupt" -Thread der Anwendung nicht ausgeführt werden kann (und mit Ereignissen umgehen kann), daher kann der Backgroundworker niemals seine fertige Funktion auslösen. Was Sie tun können, um der Anwendung das Auslösen zu ermöglichen, ist das Hinzufügen einer Application.DoEvents ();

Dies ist, was ich derzeit in einem ähnlichen Szenario benutze, und es scheint wie ein Zauber zu funktionieren!

%Vor%     
Gnutt 15.07.2016 09:29
quelle
1

Hier ist vollständiger und funktionsfähiger Code.

C # (Fensterklasse)

%Vor%

XAML

%Vor%     
Academy of Programmer 31.07.2014 16:29
quelle