Frage Deadlock beim Aufrufen des UI-Threads von einem Arbeitsthread


Ich habe einen Deadlock, wenn ich den UI-Thread von einem Arbeitsthread aufruft. Tatsächlich ist der Worker-Thread in der Aufrufzeile blockiert:

return (ucAvancementTrtFamille)mInterfaceTraitement.Invoke(d, new object[] { psFamille });

Das Seltsame ist, dass der UI-Thread (der, wenn ich falsch liege, der Hauptthread ist) inaktiv ist.

Gibt es einen Weg zu:

  1. sehen, welchen Thread ich eigentlich aufrufen möchte?
  2. Siehst du, was der Thread wirklich macht?

Wir sehen auf dem Bild unten, dass der Worker-Thread (ID 3732) in der Invoke-Zeile blockiert ist und MainThread in der Hauptfunktion der Anwendung inaktiv ist.

alt text

Edit: Hier ist der Stapel des Hauptthreads:

alt text

Edit2: Eigentlich habe ich das Programm ein zweites Mal pausiert, und hier ist, wie der Stack aussieht:

alt text

Edit3: Problemumgehung gefunden

Ich habe endlich einen Workaround gefunden. Das Problem liegt offenbar an einem asynchronen Wrapper-Rennen Zustandsproblem. Die Problemumgehung besteht darin, BeginInvoke zu verwenden und mit einem Timeout darauf zu warten. Wenn es abläuft, rufen Sie es erneut auf und wiederholen Sie die Schleife, bis es schließlich zurückkehrt. Die meiste Zeit funktioniert es tatsächlich beim zweiten Anruf.

IAsyncResult ar = mInterfaceTraitement.BeginInvoke(d, new object[] { psFamille });
            while (!ar.AsyncWaitHandle.WaitOne(3000, false))
            {
                ar = mInterfaceTraitement.BeginInvoke(d, new object[] { psFamille });
            }
            // Async call has returned - get response
            ucAvancementTrtFamille mucAvancementTrtFamille = (ucAvancementTrtFamille)mInterfaceTraitement.EndInvoke(ar);

Es ist nicht schön, aber es ist die einzige Lösung, die ich gefunden habe.


11
2017-09-21 16:48


Ursprung


Antworten:


Der Haupt-Thread sieht nicht inaktiv aus. Ihr Screenshot zeigt den aktuellen Standort von ECM.Program.Main. Das kann nicht korrekt sein, wenn es im Leerlauf ist, dann ist es in Application.Run () und pumpt die Nachrichtenschleife. Dies ist erforderlich, damit Invoke () abgeschlossen wird.

Doppelklicken Sie auf den Haupt-Thread und wechseln Sie zum Call-Stack-Fenster, um herauszufinden, was es wirklich macht.


5
2017-09-21 17:53



Hast du es versucht? BeginInvoke Anstatt von Invoke? BeginInvoke ist asynchron.


2
2017-09-21 16:54



Du hast Recht. Der Haupt-Thread ist der Eingangspunkt zu der Anwendung, die normalerweise der Ort des Anrufs ist Application.Run wodurch die Nachrichtenschleife geht. Das sollte also der UI-Thread sein, es sei denn, Sie haben etwas Ungewöhnliches in Bezug auf die Nachrichtenschleife getan, was unwahrscheinlich ist.

Im Thread-Fenster können Sie mit der rechten Maustaste auf den Haupt-Thread klicken und Switch auswählen, um den Debug-Kontext zu diesem Thread zu ändern. Das Call Stack-Fenster zeigt dann die Position der aktuell ausgeführten Methode an.

Wenn dein Worker Thread wirklich blockiert ist Control.Invoke Aufruf und der UI-Thread ist inaktiv, wie Sie behaupten, dann könnte das Problem bei der Ausführung der Anweisungen innerhalb des Stellvertreters liegen, der gemarshallt wird, oder die Nachrichtenschleife wurde noch nicht gestartet. Das spätere scheint plausibel, da Ihr Bildschirm den Standort des Hauptthreads anzeigt Main.


2
2017-09-21 17:56



Haben Sie versucht, stattdessen einen BackgroundWorker zu verwenden? Wenn Sie es verwenden, sparen Sie viel davon. Invoke und InvoqueRequired Anrufe.
Ich glaube, wenn Sie einen neuen Thread erstellen und die Ausführung der angezeigten Zeile ausführen, haben Sie keinen Deadlock. Ich werde versuchen, meinen alten Code zu finden und hier zu posten.


0
2017-09-21 17:52



Verwenden Sie Visual Studio 2008? Wenn die Antwort ja lautet, sollten Sie es mit Visual Studio 2010 versuchen. Es ist ein bekannter Fehler.

Viel Glück !


0
2017-09-22 07:51