.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
August 14th, 2009 at 10:19 am
Bunu çözmek için neler denememiştim. Çok yararlı bir yazı olmuş teşekkürler.
August 14th, 2009 at 10:35 am
İşine yaradığına çok sevindim Süleyman
yorumun için da ayrıca çok teşekkürler
February 13th, 2010 at 1:06 am
Hocam gerçekten çok süper bir yazı türkçe kaynak yok sıfır.Ellerine sağlık…
February 16th, 2010 at 10:36 am
Rica ederim Caner. İşine yaradığına sevindim.
February 26th, 2010 at 11:46 am
saygılar…
March 1st, 2010 at 12:58 pm
eyvallah…
July 17th, 2010 at 10:50 pm
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
July 18th, 2010 at 10:06 am
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.
July 18th, 2010 at 2:09 pm
Aslında ben de böyle birşey denemiştim ama başaramamıştım (c#’da daha çok yeniyim). Sonra size yazdım.
Aşağıdaki kodu çalıştırınca
Kodu çalıştırmadım
“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;
}
}
July 18th, 2010 at 9:05 pm
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…
July 19th, 2010 at 2:51 pm
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.
July 19th, 2010 at 6:51 pm
Rica ederim Semih…
Yardımcı olabildiysem ne mutlu bana