Cross-thread operation not valid!

Visual C#.NET, Yazılım Yorum Ekle

.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 :)

“Cross-thread operation not valid!” yazısına 12 Yorum var!

  1. Süleyman diyor ki;

    Bunu çözmek için neler denememiştim. Çok yararlı bir yazı olmuş teşekkürler.

  2. @bütün diyor ki;

    İşine yaradığına çok sevindim Süleyman :) yorumun için da ayrıca çok teşekkürler

  3. caner diyor ki;

    Hocam gerçekten çok süper bir yazı türkçe kaynak yok sıfır.Ellerine sağlık…

  4. @bütün diyor ki;

    Rica ederim Caner. İşine yaradığına sevindim.

  5. ramazan diyor ki;

    saygılar…

  6. @bütün diyor ki;

    eyvallah…

  7. semih diyor ki;

    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

  8. @bütün diyor ki;

    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.

  9. semih diyor ki;

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

  10. @bütün diyor ki;

    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…

  11. semih diyor ki;

    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.

  12. Ahmet BÜTÜN diyor ki;

    Rica ederim Semih…

    Yardımcı olabildiysem ne mutlu bana :)

Yorum Gönder


Tasarım:FoxTheme & Photoshop Brushes | Türkçe Çeviri:denizakin.com
Yazılar RSS Yorumlar RSS Log in