Bu sorunun cevabı, C # Kontrollerinin nasıl çalıştığına bağlıdır
Windows Forms'daki denetimler belirli bir iş parçacığına bağlıdır ve iş parçacığı güvenli değildir. Bu nedenle, farklı bir iş parçacığından bir denetimin yöntemini çağırıyorsanız, çağrıyı uygun iş parçacığına sıralamak için denetimin çağırma yöntemlerinden birini kullanmanız gerekir. Bu özellik, hangi iş parçacığının bir denetime sahip olduğunu bilmiyorsanız faydalı olabilecek bir invoke yöntemini çağırmanız gerekip gerekmediğini belirlemek için kullanılabilir.
Gönderen Control.InvokeRequired
Etkili olarak, Invoke'un yaptığı şey, aradığınız kodun, denetimin "yaşadığı" iş parçacığı üzerinde oluşmasını ve çapraz iş parçacıklı istisnaları etkili bir şekilde engellemesini sağlamaktır.
Tarihsel bir bakış açısıyla, .Net 1.1'de buna gerçekten izin veriliyordu. Bunun anlamı, herhangi bir arka plan iş parçacığından "GUI" iş parçacığı üzerinde kod çalıştırmayı deneyebileceğiniz ve bu çoğunlukla işe yarayacağıdır. Bazen, başka bir şey yaparken GUI iş parçacığını etkin bir şekilde kesintiye uğrattığınız için uygulamanızın çıkmasına neden olur. Bu Çapraz İş Parçacıklı İstisnadır - GUI başka bir şeyi boyarken bir TextBox'ı güncellemeye çalıştığınızı hayal edin.
- Hangi eylem önceliklidir?
- Her ikisinin de aynı anda olması mümkün mü?
- GUI'nin çalıştırması gereken diğer tüm komutlara ne olur?
Etkili bir şekilde, öngörülemeyen birçok sonucu olabilecek bir kuyruğu kesiyorsunuz. Invoke, yapmak istediğiniz şeyi o kuyruğa almanın etkili bir "kibar" yoludur ve bu kural .Net 2.0'dan itibaren atılan bir InvalidOperationException ile uygulanmıştır .
Perde arkasında gerçekte neler olup bittiğini ve "GUI İş Parçacığı" ile ne kastedildiğini anlamak için, bir Mesaj Pompasının veya Mesaj Döngüsünün ne olduğunu anlamak faydalıdır.
Bu aslında " Mesaj Pompası Nedir " sorusunda cevaplanmıştır ve kontrollerle etkileşim kurarken bağladığınız gerçek mekanizmayı anlamak için okumanız önerilir.
Yararlı bulabileceğiniz diğer okumalar şunları içerir:
Begin Invoke ile ne var?
Windows GUI programlamasının temel kurallarından biri, yalnızca bir denetimi oluşturan iş parçacığının içeriğine erişebilmesi ve / veya içeriklerini değiştirebilmesidir (birkaç belgelenmiş istisna dışında). Bunu başka bir iş parçacığından yapmayı deneyin ve kilitlenmeden istisnalara ve yarı güncellenmiş bir kullanıcı arayüzüne kadar öngörülemeyen davranışlar elde edeceksiniz. Başka bir iş parçacığından bir denetimi güncellemenin doğru yolu, uygulama ileti kuyruğuna uygun bir ileti göndermektir. Pompa mesajı bu mesajı yürütmek üzereyken, kontrol kendisini oluşturan iş parçacığı üzerinde güncellenecektir (unutmayın, ileti pompası ana iş parçacığı üzerinde çalışır).
ve temsili bir örnekle daha fazla kod ağırlıklı bir genel bakış için:
Geçersiz Çapraz İş Parçacığı İşlemleri
public delegate void ControlStringConsumer(Control control, string text);
public void SetText(Control control, string text) {
if (control.InvokeRequired) {
control.Invoke(new ControlStringConsumer(SetText), new object[]{control, text});
} else {
control.Text=text;
}
}
InvokeRequired'ı takdir ettiğinizde, bu çağrıları tamamlamak için bir uzatma yöntemi kullanmayı düşünebilirsiniz. Bu, Yığın Taşması sorusunda ustalıkla kapsanmıştır .
Tarihsel olarak ne olduğuna dair ilginç olabilecek başka bir yazı da var .