Invoke () ve BeginInvoke () arasındaki fark nedir


398

Sadece BeginInvoke()ve arasındaki farkları Invoke()mı merak ediyorsunuz ?

Temelde her biri ne için kullanılır.

EDIT: bir iş parçacığı nesnesi oluşturma ve bu konuda çağırmak çağırmak ve sadece BeginInvoke()bir temsilci çağırmak arasındaki fark nedir ? ya da aynı şey mi?

Yanıtlar:


568

Şunu mu demek istediniz: Delegate.Invoke/ BeginInvokeveya Control.Invoke/ BeginInvoke?

  • Delegate.Invoke: Aynı iş parçacığında senkronize olarak yürütür.
  • Delegate.BeginInvoke: Bir threadpooliş parçacığı üzerinde zaman uyumsuz olarak yürütülür .
  • Control.Invoke: Kullanıcı arabirimi iş parçacığında yürütülür, ancak çağıran iş parçacığı devam etmeden önce tamamlanmasını bekler.
  • Control.BeginInvoke: UI iş parçacığında yürütülür ve çağıran iş parçacığı tamamlanmasını beklemez.

Tim'in cevabı ne zaman kullanmak isteyebileceğinizden bahsediyor BeginInvoke- çoğunlukla buna rağmen Delegate.BeginInvoke, şüpheleniyorum.

Windows Forms uygulamaları için, genellikle kullanmanız gerektiğini öneririm BeginInvoke. Bu şekilde, örneğin kilitlenme hakkında endişelenmenize gerek yoktur - ancak kullanıcı arayüzünün bir sonraki bakışınızda güncellenmemiş olabileceğini anlamanız gerekir! Özellikle, UI iş parçacığının görüntüleme amacıyla kullanmak üzere olabileceği verileri değiştirmemelisiniz. Örneğin, ve özelliklerine Personsahip FirstNameve LastNameyaptıysanız:

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

Ardından kullanıcı arayüzü "Keyser Spacey" i görüntüleyebilir. ("Kevin Soze" i göstermesi için dışarıdan bir şans var ama sadece bellek modelinin tuhaflığıyla.)

Ancak, bu tür bir sorun yoksa, Control.BeginInvokedoğru almak daha kolaydır ve arka plan iş parçacığının iyi bir sebep için beklemek zorunda kalmasını önleyecektir. Windows Forms ekibinin Control.BeginInvoke"ateşle ve unut" biçiminde kullanabileceğinizi garanti ettiğini unutmayın EndInvoke. Bu genel olarak zaman uyumsuz çağrılar için geçerli değildir: normalde her BeginXXX, genellikle geri aramada karşılık gelen bir EndXXX çağrısına sahip olmalıdır.


4
O zaman ppl neden InvInvoke Over Beingvoke kullanmalı? Invoke'u kullanmanın bazı avantajları olmamalı. Her ikisi de arka planda işlemleri yürütür, sadece biri aynı iş parçacığında, diğeri farklı iş parçacığında mı?
yeeen

2
@Jon: Dispatcher.BeginInvoke kodumu iyi çalışıyor ve Dispatcher.Invoke benim uygulama birkaç saniye bekletmek beni daha sonra başlattıktan sonra tüm kontrolleri başlatır, Ben tam olarak hangi yerde sıkışmış bulmak için bana yardımcı olabilir misiniz ?
SharpUrBrain

6
@SharpUrBrain: Control.BeginInvoke, Dispatcher.BeginInvoke'a eşdeğerdir, ancak WinForms için (Dispatcher WPF ve Silverlight içindir).
Jon Skeet

4
@SharpUrBrain: Yorumlarda devam etmek yerine belirli bir soru sormanızı öneririm - ve elbette aynı sorunun daha önce başka biri tarafından sorulup sorulmadığını kontrol edin.
Jon Skeet

2
@AZ: Evet, "UI iş parçacığında" ile, söz konusu Kontrol'ün tutamağına sahip olan belirli "UI iş parçacığında" anlamına gelir. Tipik olarak, yalnızca bir UI iş parçacığı vardır, ancak birden fazla UI iş parçacığına sahip olmak mümkündür ve gelişmiş uygulamalarda bunları istemenizin nedenleri vardır. Teknik olarak, herhangi bir (normal?) İş parçacığı bir UI ileti pompası başlatabilir ve bir UI iş parçacığı olabilir - ve daha sonra ileti pompasını kapatabilir ve artık bir UI iş parçacığı olamaz. (Ama bunun bir threadpool iplik üzerinde denemek için bir şey olmadığını varsayalım.)
Rob Parker

46

Jon Skeet'in cevabına dayanarak, bir temsilci çağırmak ve geçerli iş parçacığı devam etmeden önce yürütülmesini beklemek istediğiniz zamanlar vardır. Bu durumlarda Çağırma çağrısı istediğiniz şeydir.

Çok iş parçacıklı uygulamalarda, özellikle de temsilci G / Ç (temsilci ve iş parçacığı bloğunuzu oluşturabilir) gerçekleştirirse, bir iş parçacığının yürütmeyi bitirmek için bir temsilci üzerinde beklemesini istemeyebilirsiniz.

Bu durumlarda BeginInvoke yararlı olacaktır. Bunu arayarak, temsilciye başlamasını söylersiniz, ancak iş parçacınız delege ile paralel olarak başka şeyler yapmakta serbesttir.

BeginInvoke kullanımı kodunuzun karmaşıklığını artırır, ancak geliştirilmiş performansın karmaşıklığa değdiği zamanlar vardır.


27

Arasındaki fark Control.Invoke()ve Control.BeginInvoke()olduğu

  • BeginInvoke()GUI iş parçacığında zamanuyumsuz eylemi zamanlar. Eşzamansız eylem zamanlandığında, kodunuz devam eder. Bir süre sonra (tam olarak ne zaman olduğunu bilmiyorsunuz) eşzamansız işleminiz yürütülecek
  • Invoke() eşzamansız eyleminizi (GUI iş parçacığında) yürütecek ve işleminiz tamamlanana kadar bekleyecektir.

Mantıksal bir sonuç, geçtiğiniz bir temsilcinin Invoke()çıkış parametrelerine veya bir dönüş değerine sahip BeginInvoke()olabileceği, ancak ilettiğiniz bir temsilci yapamayacağıdır (sonuçları almak için EndInvoke kullanmanız gerekir).


20

Farklılıklarının etkisini görmek için kısa, çalışan bir örnek vermek

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

Kullanım Eğer BeginInvoke MessageBox metin güncelleme eşzamanlı çıkar. Kullanım Eğer çağırır , MessageBox 3 saniyelik uykudan sonra açılır. Bu nedenle, eşzamansız ( BeginInvoke ) ve eşzamanlı ( Çağırma ) çağrısının etkisini gösterir .


9

Delegate.BeginInvoke (), bir temsilci çağrısını eşzamansız olarak sıraya alır ve denetimi hemen döndürür. Delegate.BeginInvoke () kullanırken, sonuçları almak için geri arama yönteminde Delegate.EndInvoke () yöntemini çağırmanız gerekir.

Delegate.Invoke () eşit olarak aynı iş parçacığında temsilci çağırır.

MSDN Makalesi


8

Invoke () 'in neden ve ne zaman kullanılacağını eklemeniz yeterlidir.

Hem Invoke () hem de BeginInvoke (), dağıtım programı iş parçacığına belirttiğiniz kodu marshal.

Ancak BeginInvoke () öğesinin aksine, Invoke (), dağıtım programı kodunuzu yürütene kadar iş parçacığınızı durdurur. Kullanıcı bir tür geri bildirim sağlayana kadar eşzamansız bir işlemi duraklatmanız gerekirse Invoke () yöntemini kullanmak isteyebilirsiniz.

Örneğin, Tamam / İptal iletişim kutusunu gösteren bir kod snippet'i çalıştırmak için Invoke () öğesini çağırabilirsiniz. Kullanıcı bir düğmeyi tıklattıktan ve marshaled kodunuz tamamlandıktan sonra, invoke () yöntemi geri döner ve kullanıcının yanıtına göre hareket edebilirsiniz.

Bkz. Pro WPF, C # bölüm 31

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.