6 Stimmen

Control.BeginInvoke() Vs Dispatcher Vs SynchronizationContext Vs .. - ZUVERLÄSSIGKEIT

Es wurde viel darüber diskutiert, wie ein UI-Thread von einem Arbeits-Thread aus aufgerufen werden kann, und wir wissen, warum man `BeginInvoke()` anstelle von `Invoke()` verwenden sollte. Ich habe kürzlich diese Frage veröffentlicht und nach einigen Recherchen festgestellt, dass es zumindest drei verschiedene Arten (intern können sie gleich sein) gibt, etwas auf dem UI-Thread (asynchron) aufzurufen.

  1. Control.BeginInvoke()
  2. Verwendung der SynchronizatoinContext Klasse
  3. Verwenden von Dispatcher.BeginInvoke(Priorität..)

Kann mir jemand sagen, welcher Weg zuverlässig ist, um eine Methode asynchron auf dem UI-Thread auszuführen? Irgendwelche Erfahrungen? Ich sehe, dass `Dispatcher.BeginInvoke` eine Prioritätskomponente hat, macht das es zuverlässiger?

Kontext:
Wir verwenden `someControl.BeginInvoke()`, aber manchmal (leider nur in der Produktionsumgebung für Endbenutzer) wird der an `BeginInvoke` übergebene Delegat nie ausgeführt, was mich glauben lässt, dass die Post Nachricht, die er erstellt, verloren geht. Wir möchten einen zuverlässigen Weg finden, um mit dem UI-Thread zu kommunizieren. `control.Invoke()` hängt manchmal die UI auf, also wollen wir auch dort nicht hingehen.

0 Stimmen

Verwechseln Sie WinForms nicht mit WPF.

0 Stimmen

Ich habe ein ähnliches Problem...Hast du zufällig das Problem beheben können?

0 Stimmen

Gleiche hier, irgendein Update?

0voto

Kieren Johnstone Punkte 40059

Sie alle funktionieren wie sie sollten, wenn Sie BeginInvoke aufrufen und manchmal passiert nichts, gibt es ein Problem in der Umgebung oder im Aufrufcode, wahrscheinlich - es liegt nicht daran, dass BeginInvoke unzuverlässig ist. Nun ja - es könnte ein Fehler sein, aber es ist weit weniger wahrscheinlich.

Vielleicht könnten Sie mehr Kontext geben und wir können bei der Diagnose helfen.

0 Stimmen

Vielen Dank für die Antwort. Ich habe ein ähnliches Szenario in unserem Code. stackoverflow.com/questions/6270514/…

0 Stimmen

Hallo karephul, das ist interessant, hilft jedoch in diesem Fall nicht viel, da sie auch keine Antwort gefunden haben. Was ist Ihr grundlegendes Setup in Bezug auf Threads, Prozesse, Sperren, etc.?

0 Stimmen

Oh... ist das dasselbe Problem? Einfach hier neu gepostet?

0voto

Steel Punkte 125

SynchronizationContext ist abstrakter und anpassungsfähiger in den meisten Fällen. Es ist ein Wrapper einer spezifischen Implementierung. MSDN sagt "Anbieter von Synchronisierungsmodellen können diese Klasse erweitern und ihre eigenen Implementierungen für diese Methoden bereitstellen".

0 Stimmen

SynchronizationContext wird hier bevorzugt: social.msdn.microsoft.com/Forums/en-US/async/thread/…

0voto

Mark Lakata Punkte 18998

Du solltest vorsichtig sein mit Lambda-Funktionen und BeginInvoke. Ich hatte Code wie diesen, der zu allerlei seltsamem Verhalten führte.

MyThing ding;
while( GetThing(ref ding)) {
    control.BeginInvoke((Action)(() => control.Text = ding.ToString()));
}

Das Problem ist, dass ding nicht ausgewertet wird, wenn du die Lambda-Funktion erstellst. Es wird ausgewertet, wenn die Lambda-Funktion ausgeführt wird. Aber es ist an eine Variable gebunden, die sich gleichzeitig im Producer-Thread ändert.

Du kannst dieses Problem beheben, indem du eine lokale Variablekopie von ding deklarierst

MyThing ding;
while( GetThing(ref ding)) {
  MyThing ding_x = ding;
  control.BeginInvoke((Action)(() => control.Text = ding_x.ToString()));
}

Oder du kannst die BeginInvoke-Hässlichkeit in ein Wrapper setzen

MyThing ding;
while( GetThing(ref ding)) {
  SetText(ding);
}

void SetText(MyThing ding) {
  control.BeginInvoke((Action)(() => control.Text = ding.ToString()));
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X