457 Stimmen

Was ist der Unterschied zwischen Invoke() und BeginInvoke()?

Ich frage mich nur, was der Unterschied zwischen BeginInvoke() y Invoke() sind?

Vor allem, wofür sie jeweils verwendet werden sollen.

EDIT: Was ist der Unterschied zwischen dem Erstellen eines Threading-Objekts und dem Aufruf von invoke für dieses und dem einfachen Aufruf von BeginInvoke() auf einen Delegierten? oder sind sie dasselbe?

640voto

Jon Skeet Punkte 1325502

Meinen Sie Delegate.Invoke / BeginInvoke o Control.Invoke / BeginInvoke ?

  • Delegate.Invoke : Wird synchron, auf demselben Thread, ausgeführt.
  • Delegate.BeginInvoke : Wird asynchron ausgeführt, auf einer threadpool Thema.
  • 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 die Fertigstellung.

In Tims Antwort wird erwähnt, wann Sie Folgendes verwenden sollten BeginInvoke - obwohl sie sich hauptsächlich an Delegate.BeginInvoke vermute ich.

Für Windows Forms-Anwendungen würde ich vorschlagen, dass Sie in der Regel verwenden. BeginInvoke . Auf diese Weise müssen Sie sich zum Beispiel keine Sorgen über Deadlocks machen - aber Sie müssen sich darüber im Klaren sein, dass die Benutzeroberfläche möglicherweise noch nicht aktualisiert wurde, wenn Sie sie das nächste Mal betrachten! Insbesondere sollten Sie keine Daten ändern, die der UI-Thread vielleicht gerade für die Anzeige verwenden will. Zum Beispiel, wenn Sie eine Person con FirstName y LastName Eigenschaften, und das haben Sie getan:

person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";

Dann kann es gut sein, dass die Benutzeroberfläche "Keyser Spacey" anzeigt (es besteht eine geringe Chance, dass sie "Kevin Soze" anzeigt, aber nur aufgrund der Seltsamkeiten des Speichermodells).

Es sei denn, Sie haben diese Art von Problem, Control.BeginInvoke ist einfacher zu bewerkstelligen und verhindert, dass Ihr Hintergrund-Thread ohne Grund warten muss. Beachten Sie, dass das Windows Forms Team garantiert hat, dass Sie Control.BeginInvoke nach dem "Feuer und Vergessen"-Prinzip, d. h. ohne jemals die EndInvoke . Dies gilt nicht für asynchrone Aufrufe im Allgemeinen: Normalerweise sollte jeder BeginXXX-Aufruf einen entsprechenden EndXXX-Aufruf haben, normalerweise im Callback.

57voto

Tim Stewart Punkte 5027

Aufbauend auf der Antwort von Jon Skeet, 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 Invoke-Aufruf das, was Sie wollen.

In Anwendungen mit mehreren Threads möchten Sie vielleicht nicht, dass ein Thread auf einen Delegaten wartet, um die Ausführung zu beenden, insbesondere wenn dieser Delegat E/A durchführt (was dazu führen könnte, dass der Delegat und Ihr Thread blockieren).

In diesen Fällen wäre der BeginInvoke nützlich. Indem Sie ihn aufrufen, teilen Sie dem Delegaten mit, dass er starten soll, aber Ihr Thread kann dann parallel zum Delegaten andere Dinge tun.

Die Verwendung von BeginInvoke erhöht die Komplexität Ihres Codes, aber es gibt Zeiten, in denen die verbesserte Leistung die Komplexität wert ist.

33voto

Sujit Punkte 3507

Der Unterschied zwischen Control.Invoke() y Control.BeginInvoke() ist,

  • BeginInvoke() wird die asynchrone Aktion auf dem GUI-Thread geplant. Wenn die asynchrone Aktion geplant ist, wird Ihr Code fortgesetzt. Einige Zeit später (Sie wissen nicht genau, wann) wird Ihre asynchrone Aktion ausgeführt
  • Invoke() führt Ihre asynchrone Aktion (auf dem GUI-Thread) aus und wartet, bis Ihre Aktion abgeschlossen ist.

Eine logische Schlussfolgerung ist, dass ein Delegat, den Sie an Invoke() kann Out-Parameter oder einen Rückgabewert haben, während ein Delegat, den Sie an BeginInvoke() nicht möglich (Sie müssen EndInvoke verwenden, um die Ergebnisse abzurufen).

28voto

KMC Punkte 18872

Nur ein kurzes Beispiel, um die Auswirkungen der Unterschiede zu verdeutlichen

new Thread(foo).Start();

private void foo()
{
  this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    (ThreadStart)delegate()
    {
        myTextBox.Text = "bing";
        Thread.Sleep(TimeSpan.FromSeconds(3));
    });
  MessageBox.Show("done");
}

Wenn Sie BeginInvoke wird gleichzeitig mit der Textaktualisierung eine MessageBox eingeblendet. Wenn Sie Rufen Sie auf. Die MessageBox erscheint nach den 3 Sekunden Schlaf. So wird die Wirkung einer asynchronen ( BeginInvoke ) und eine synchrone ( Rufen Sie auf. ) aufrufen.

10voto

Aaron Palmer Punkte 8702

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 Callback-Methode aufrufen, um die Ergebnisse zu erhalten.

Delegate.Invoke() ruft den Delegaten synchron im selben Thread auf.

MSDN-Artikel

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