2009-04-23 11 views
26

Mit C# 2.0 und dem MethodInvoker-Delegaten habe ich eine GUI-Anwendung, die ein Ereignis vom GUI-Thread oder von einem Worker-Thread erhält.Mit C# MethodInvoker.Invoke() für eine GUI-App ... ist das gut?

Ich benutze das folgende Muster für das Ereignis in der Form der Handhabung:

private void SomeEventHandler(object sender, EventArgs e) 
{ 
    MethodInvoker method = delegate 
     { 
      uiSomeTextBox.Text = "some text"; 
     }; 

    if (InvokeRequired) 
     BeginInvoke(method); 
    else 
     method.Invoke(); 
} 

dieses Musters unter Verwendung Ich habe nicht den tatsächlichen UI-Code kopieren, aber was ich bin mir nicht sicher ist, ob diese Methode gut ist .

Insbesondere die Linie

method.Invoke() 

es einen weiteren Thread nicht verwendet zum Aufrufen oder etwas nach Methode auf dem GUI-Thread auf einen direkten Aufruf nicht übersetzen?

Antwort

21

Der Aufruf method.Invoke() führt den Delegaten für den aktuell ausgeführten Thread aus. Die Verwendung von BeginInvoke(method) stellt sicher, dass der Delegat für den GUI-Thread aufgerufen wird.

Dies ist die korrekte Methode zur Vermeidung von Code-Duplizierung, wenn dieselbe Methode sowohl vom GUI-Thread als auch von anderen Threads aufgerufen werden kann.

+0

Dank! Ich war fest auf mit Methode.Invoke und sogar Invoke ((MethodInvoker). Gehen Sie zurück zu BeginInvoke hat den Trick. –

0

Es macht den Anruf auf dem gleichen Thread. Sie können dies überprüfen, indem Sie den Code durchgehen. Mit diesem Ansatz ist nichts falsch.

2

Bei WinForms sendet der Aufruf Control.Invoke(Delegate) eine Nachricht an die Nachrichtenpumpe der Benutzeroberfläche. Der Thread verarbeitet dann die Nachricht und ruft den Delegaten auf. Sobald es verarbeitet wurde, hört Invoke auf, zu blockieren, und der aufrufende Thread wird fortgesetzt, Ihren Code auszuführen.

5

Beachten Sie, dass Control.InvokeRequired false zurückgibt, wenn Sie sich im Hintergrund Thread UND Control.IsHandleCreated ist falsch. Ich würde den Code mit einem Debug.Assert schützen, das auf nicht verwaltete Handle-Erstellung überprüft.

14

Ich persönlich mag diese Methode:

private void ExecuteSecure(Action a) 
{ 
    if (InvokeRequired) 
     BeginInvoke(a); 
    else 
     a(); 
} 

Und dann können Sie Einzeiler wie folgt schreiben:

ExecuteSecure(() => this.Enabled = true); 
+0

Etwas sieht hier nicht richtig. InvokeRequired funktioniert auf einem Steuerelement, Sie sind nur da draußen mit nichts. Was bedeutet es? – Craig

+0

InvokeRequired ist dasselbe wie this.InvokeRequired. –