Yanıtlar:
Şunu mu demek istediniz: Delegate.Invoke
/ BeginInvoke
veya Control.Invoke
/ BeginInvoke
?
Delegate.Invoke
: Aynı iş parçacığında senkronize olarak yürütür.Delegate.BeginInvoke
: Bir threadpool
iş 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 Person
sahip FirstName
ve LastName
yaptı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.BeginInvoke
doğ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.
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.
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ülecekInvoke()
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).
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 .
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.
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