.NET kullanan yazılımcı arkadaşlar uygulama geliştirirken zaman zaman aşağıdakine benzer bir hata alabilirsiniz;
Cross-thread operation not valid: Control ‘xxxxx’ accessed from a thread other than the thread it was created on.
Bu istisnai durum herhangi bir kontrole ya da kontrolün özelliklerine, kontrolün oluşturulduğu Thread dışında farklı bir Thread üzerinden erişmeye çalışıldığında ortaya çıkıyor. Dolayısıyla bu durum daha çok Multi-Threading gerektiren uygulamalarda karşımıza çıkıyor. Peki bu sorunu nasıl çözeceğiz? İşte bu noktada .NET’in güçlü yapılarından Delegate (Temsilci) lere başvuracağız. Bu sorunu ortadan kaldırmak Delegate’ler ile inanılmaz kolay. Nasıl mı? Şöyle, bir örnekle açıklayalım;
delegate void updateLabelTextDelegate(string newText); private void updateLabelText(string newText) { if (label1.InvokeRequired) { // worker thread updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText); label1.Invoke(del, new object[] { newText }); } else { // UI thread label1.Text = newText; } } |
burada yapmak istediğimiz şey, uygulamamızın içerisinde bulunan Label1 adlı Label kontrolünün
Text özelliğine farklı Thread’ ler üzerinde de erişebilmek. Öncelikle ilgili kontrolün Text özelliğini değiştiren bir metodu temsil edene bir temsilci tanımlamak (ve tabii ki metodu da). İşte bu amaçla updateLabelTextDelegate adlı, uygulama içerisinde updateLabelText() metodunu temsil edebilecek bir temsilci tanımlıyoruz. Metodumuzun içerisinde ise, ilgili kontrolün eğer faklı bir Thread üzerinden erişilmişse ayrı bir invocation gerektirip gerektirmediğini kontrol ediyoruz. Artık updateLabelText() metodunu gönül rahatlığı ile uygumamızın herhangi bir yerinde, herhangi bir Thread içerisinde çağırabiliriz. Hepsi bu kadar kolay 🙂
Hepsi bu kadar 🙂
Bunu çözmek için neler denememiştim. Çok yararlı bir yazı olmuş teşekkürler.
İşine yaradığına çok sevindim Süleyman 🙂 yorumun için da ayrıca çok teşekkürler
Hocam gerçekten çok süper bir yazı türkçe kaynak yok sıfır.Ellerine sağlık…
Rica ederim Caner. İşine yaradığına sevindim.
saygılar…
eyvallah…
Hocam, çok teşekkür ederim. Çok yararlı ve sade bir kod.
Birşey sormak istiyorum. Bunun gibi onlarca label veya text varsa nasıl olacak her seferinde ayrı ayrı mı yazacağız
Teşekürler,
Birden fazla kontrol varsa, ben şöyle bir yöntemi tercih ediyorum..Yukarıdaki metota parametre olarak kontrolü de gönderiyorum 🙂
delegate void updateLabelTextDelegate(string newText);
private void updateLabelText(Control control, string newText)
{
if (control.InvokeRequired)
{
// worker thread
updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);
control.Invoke(del, new object[] { newText });
}
else
{
// UI thread
Label lab = (Label)control;
lab.Text = newText;
}
}
gibi…Umarım yardımı dokunur.
Aslında ben de böyle birşey denemiştim ama başaramamıştım (c#’da daha çok yeniyim). Sonra size yazdım.
Kodu çalıştırmadım 🙁 🙁 Aşağıdaki kodu çalıştırınca
“No overload for ‘updateLabelText’ matches delegate ‘RF_Remote_1.Form1.updateLabelTextDelegate'”
hatasını alıyorum. 🙁
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
mesaj = serialPort1.ReadLine();
updateLabelText(label1, mesaj);
}
private void updateLabelText(Control control, string newText)
{
if (control.InvokeRequired)
{
// worker thread
updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);
control.Invoke(del, new object[] { newText });
}
else
{
// UI thread
Label lab = (Label)control;
lab.Text = newText;
}
}
Hiçbirimiz anamızın karnında öğrenmedik bunları 🙂 merak etme yavaş yavaş tecrübe kazanırsın.
Delegate tipini değitirmemiz lazım…Önceden updateLabelTextDelegate delegate’imiz yalnızca string tipinde bir parametre alıyordu ona şimdi bir de Control adlı yeni parametreyi aktarmamız lazım.
Yani,
delegate void updateLabelTextDelegate(string newText);
tanımını
delegate void updateLabelTextDelegate(Control control, string newText);
şeklinde değiştirdikten sonra,
control.Invoke(del, new object[] { newText });
satırını da,
control.Invoke(del, new object[] {control, newText });
şeklinde değiştirirsen sanırım sorun çözülecektir.
Yine de bir sorunla karşılaşırsan çekinme 🙂 Ben buralardayım…
Evet Ahmet hocam. Çok teşekkür ederim. İşimi çok kolaylaştıran ve programı ağırlaştırmayan bir kod oldu.
İyi çalışmalar Diliyorum.
Rica ederim Semih…
Yardımcı olabildiysem ne mutlu bana 🙂
çok teşekkür ederim.epey işime yaradı
Rica ederim Rasim.
yav kardeşim çok saolasın, harikasın valla 🙂 4 saattir bu hatayla uğraşıyodum en sonunda sayende hallettim.
CheckForIllegalCrossThreadCalls = false; de işe yarıyor. Teşekkürler Ahmet Hocam.