Meinst du Delegate.Invoke
/ BeginInvoke
oder Control.Invoke
/ BeginInvoke
?
Delegate.Invoke
: Wird synchron im selben Thread ausgeführt.
Delegate.BeginInvoke
: Wird asynchron in einem threadpool
Thread ausgeführt.
Control.Invoke
: Wird auf dem UI-Thread ausgeführt, aber der aufrufende Thread wartet auf den Abschluss, bevor er fortfährt.
Control.BeginInvoke
: Wird auf dem UI-Thread ausgeführt und der aufrufende Thread wartet nicht auf den Abschluss.
Tims Antwort erwähnt, wann Sie sie verwenden möchten BeginInvoke
- obwohl sie vermutlich hauptsächlich darauf ausgerichtet Delegate.BeginInvoke
war.
Für Windows Forms-Apps würde ich empfehlen, dass Sie normalerweise verwenden BeginInvoke
. Auf diese Weise müssen Sie sich zum Beispiel keine Gedanken über Deadlocks machen - aber Sie müssen verstehen, dass die Benutzeroberfläche möglicherweise nicht aktualisiert wurde, wenn Sie sie das nächste Mal betrachten! Insbesondere sollten Sie keine Daten ändern, die der UI-Thread möglicherweise für Anzeigezwecke verwendet. Wenn Sie beispielsweise ein Person
with FirstName
und LastName
Eigenschaften haben und Folgendes getan haben:
person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";
Dann zeigt die Benutzeroberfläche möglicherweise "Keyser Spacey" an. (Es besteht die Möglichkeit, dass "Kevin Soze" angezeigt wird, jedoch nur durch die Verrücktheit des Speichermodells.)
Es sei denn, Sie haben diese Art von Problem, ist jedoch Control.BeginInvoke
einfacher zu beheben und verhindert, dass Ihr Hintergrund-Thread ohne guten Grund warten muss. Beachten Sie, dass das Windows Forms-Team garantiert hat, dass Sie es Control.BeginInvoke
"Feuer und Vergessen" verwenden können - dh ohne jemals anzurufen EndInvoke
. Dies gilt im Allgemeinen nicht für asynchrone Aufrufe: Normalerweise sollte jeder BeginXXX einen entsprechenden EndXXX-Aufruf haben, normalerweise im Rückruf.
Aufbauend auf Jon Skeets Antwort gibt es Zeiten, in denen Sie einen Delegaten aufrufen und warten möchten, bis seine Ausführung abgeschlossen ist, bevor der aktuelle Thread fortgesetzt wird. In diesen Fällen ist der Aufruf von Invoke genau das, was Sie wollen.
In Multithreading-Anwendungen möchten Sie möglicherweise nicht, dass ein Thread auf einen Delegaten wartet, um die Ausführung zu beenden, insbesondere wenn dieser Delegat E / A ausführt (wodurch der Delegat und Ihr Thread blockiert werden könnten).
In diesen Fällen wäre BeginInvoke hilfreich. Wenn Sie es aufrufen, weisen Sie den Delegaten an, zu starten, aber dann kann Ihr Thread andere Dinge parallel zum Delegaten ausführen.
Die Verwendung von BeginInvoke erhöht die Komplexität Ihres Codes, aber manchmal ist die verbesserte Leistung die Komplexität wert.
quelle
Der Unterschied zwischen
Control.Invoke()
undControl.BeginInvoke()
ist,BeginInvoke()
plant die asynchrone Aktion im GUI-Thread. Wenn die asynchrone Aktion geplant ist, wird Ihr Code fortgesetzt. Einige Zeit später (Sie wissen nicht genau wann) wird Ihre asynchrone Aktion ausgeführtInvoke()
führt Ihre asynchrone Aktion (im GUI-Thread) aus und wartet, bis Ihre Aktion abgeschlossen ist.Eine logische Schlussfolgerung ist, dass ein Delegat, an den Sie übergeben,
Invoke()
Out-Parameter oder einen Rückgabewert haben kann, während ein Delegat, an den Sie übergeben,BeginInvoke()
dies nicht kann (Sie müssen EndInvoke verwenden, um die Ergebnisse abzurufen).quelle
Nur um ein kurzes, funktionierendes Beispiel zu geben, um einen Effekt ihres Unterschieds zu sehen
Wenn Sie BeginInvoke verwenden , wird MessageBox gleichzeitig mit der Textaktualisierung angezeigt . Wenn Sie Invoke verwenden , wird die MessageBox nach dem 3-Sekunden-Ruhezustand angezeigt. Daher wird der Effekt eines asynchronen ( BeginInvoke ) und eines synchronen ( Invoke ) Aufrufs angezeigt .
quelle
Delegate.BeginInvoke () stellt den Aufruf eines Delegaten asynchron in die Warteschlange und gibt die Kontrolle sofort zurück. Wenn Sie Delegate.BeginInvoke () verwenden, sollten Sie Delegate.EndInvoke () in der Rückrufmethode aufrufen, um die Ergebnisse zu erhalten.
Delegate.Invoke () ruft den Delegaten synchron im selben Thread auf.
MSDN-Artikel
quelle
Fügen Sie einfach hinzu, warum und wann Invoke () verwendet werden soll.
Sowohl Invoke () als auch BeginInvoke () marshallen den Code, den Sie für den Dispatcher-Thread angegeben haben.
Im Gegensatz zu BeginInvoke () blockiert Invoke () Ihren Thread, bis der Dispatcher Ihren Code ausführt. Möglicherweise möchten Sie Invoke () verwenden, wenn Sie einen asynchronen Vorgang anhalten müssen, bis der Benutzer eine Art Feedback gegeben hat.
Sie können beispielsweise Invoke () aufrufen, um einen Codeausschnitt auszuführen, der ein Dialogfeld OK / Abbrechen anzeigt. Nachdem der Benutzer auf eine Schaltfläche geklickt hat und Ihr gemarshallter Code abgeschlossen ist, kehrt die invoke () -Methode zurück und Sie können auf die Antwort des Benutzers reagieren.
Siehe Pro WPF in C # Kapitel 31
quelle