Jaka jest różnica między Invoke () a BeginInvoke()

Zastanawiam się, jaka jest różnica między BeginInvoke() a Invoke()?

Głównie to, do czego każdy z nich byłby używany.

EDIT: Jaka jest różnica między utworzeniem obiektu wątkowego a wywołaniem wywołania na tym obiekcie, a wywołaniem BeginInvoke() Na delegacie? czy to to samo?

Author: ArunPratap, 2008-10-23

6 answers

Czy masz na myśli Delegate.Invoke/BeginInvoke lub Control.Invoke/BeginInvoke?

  • Delegate.Invoke: wykonuje synchronicznie, na tym samym wątku.
  • Delegate.BeginInvoke: wykonuje asynchronicznie, na wątku threadpool.
  • Control.Invoke: wykonuje w wątku UI, ale wywołanie wątku czeka na zakończenie przed kontynuowaniem.
  • Control.BeginInvoke: uruchamia wątek interfejsu użytkownika i wywołanie wątku nie czeka na zakończenie.

Odpowiedź Tima wspomina, kiedy możesz chcieć użyć BeginInvoke - chociaż była głównie nastawiona na Delegate.BeginInvoke, podejrzewam.

W przypadku aplikacji Windows Forms sugerowałbym, aby zazwyczaj używać BeginInvoke. W ten sposób nie musisz się martwić o impas, na przykład - ale musisz zrozumieć, że interfejs nie został zaktualizowany do czasu następnego spojrzenia na niego! W szczególności nie należy modyfikować danych, które wątek interfejsu może wykorzystywać do celów wyświetlania. Na przykład, jeśli masz Person z FirstName i LastName właściwości, a zrobiłeś:

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

Następnie UI może skończyć się wyświetlaniem "Keyser Spacey". (Istnieje zewnętrzna szansa, że może wyświetlać "Kevin Soze", ale tylko dzięki dziwności modelu pamięci.)

Chyba że masz tego rodzaju problem, jednak Control.BeginInvoke jest łatwiejsze do naprawienia i pozwoli uniknąć czekania na Twój wątek w tle bez powodu. Zauważ, że zespół Windows Forms zagwarantował, że możesz używać Control.BeginInvoke w sposób "odpal i zapomnij" - tzn. bez wywoływania EndInvoke. Nie dotyczy to wywołań asynchronicznych w ogólne: normalnie każdy BeginXXX powinien mieć odpowiednie połączenie EndXXX, zwykle w wywołaniu zwrotnym.

 584
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-23 14:33:18

Bazując na odpowiedzi Jona Skeeta, są chwile, kiedy chcesz wywołać delegata i poczekać, aż jego wykonanie się zakończy, zanim bieżący wątek będzie kontynuowany. W takich przypadkach wywołanie jest tym, czego chcesz.

W aplikacjach wielowątkowych, możesz nie chcieć, aby wątek czekał na delegata, aby zakończyć wykonywanie, zwłaszcza jeśli ten delegat wykonuje operacje We/Wy (co może sprawić, że delegat i Twój wątek będą blokować).

W takich przypadkach przydatny byłby BeginInvoke. Nazywając go, mówisz delegatowi, aby zaczął, ale wtedy Twój wątek może robić inne rzeczy równolegle z delegatem.

Korzystanie z BeginInvoke zwiększa złożoność kodu, ale są chwile, kiedy lepsza wydajność jest warta złożoności.

 49
Author: Tim Stewart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-23 12:49:49

Różnica między Control.Invoke() a Control.BeginInvoke() wynosi,

  • BeginInvoke() zaplanuje asynchroniczną akcję w wątku GUI. Gdy zaplanowana jest akcja asynchroniczna, kod jest kontynuowany. Jakiś czas później (nie wiesz dokładnie kiedy) zostanie wykonana twoja asynchroniczna akcja
  • Invoke() wykona asynchroniczną akcję (w wątku GUI) i odczekuje do zakończenia akcji.

Logicznym wnioskiem jest to, że delegat, do którego przekazujesz Invoke() może mieć out-parameters lub return-value, podczas gdy delegat, który przekazujesz BeginInvoke(), nie może (musisz użyć EndInvoke, aby pobrać wyniki).

 30
Author: Sujit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-11 07:07:32

Aby dać krótki, działający przykład, aby zobaczyć efekt ich różnicy

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");
}

Jeśli użyjesz BeginInvoke , MessageBox wyskakuje równocześnie z aktualizacją tekstu. Jeśli używasz wywołaj, MessageBox wyskakuje po 3 sekundowym uśpieniu. Stąd, pokazując efekt asynchronicznego (BeginInvoke) i synchronicznego (Invoke) wywołania.

 20
Author: KMC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-14 05:11:39

Delegat.BeginInvoke () asynchronicznie kolejkuje wywołanie delegata i natychmiast zwraca kontrolę. Podczas korzystania z funkcji Delegate.BeginInvoke (), powinieneś wywołać Delegate.EndInvoke() w metodzie callback, aby uzyskać wyniki.

Delegat.Wywołanie() synchronicznie wywołuje delegata w tym samym wątku.

Artykuł MSDN

 9
Author: Aaron Palmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-23 13:11:34

Wystarczy dodać why I when do użycia Invoke ().

Zarówno Invoke () jak i BeginInvoke () wywołują kod podany w wątku dyspozytora.

Ale w przeciwieństwie do BeginInvoke (), Invoke () zatrzymuje Twój wątek dopóki dyspozytor nie wykona Twojego kodu. możesz użyć Invoke (), jeśli chcesz wstrzymać operację asynchroniczną, dopóki użytkownik nie dostarczy informacji zwrotnej.

Na przykład, można wywołać wywołanie Invoke (), aby uruchomić fragment kodu, który wyświetla okno dialogowe OK/Cancel box. Gdy użytkownik kliknie przycisk i twój kod zostanie ukończony, metoda invoke() powróci, a Ty będziesz mógł zareagować na odpowiedź użytkownika.

Zobacz Pro WPF w C# Rozdział 31

 9
Author: Ingako,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-06 04:33:27