Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

WPF’te “The Calling Thread Cannot Access This Object Because A Different Thread Owns It” Hatası ve Çözümü

Merhaba,
Hatırlarsanız eğer C# Winfows Forms uygulamalarına özel olarak C#’ta Bir İş Parçacığını Farklı Bir İş Parçacığında Denetlemek başlıklı makalemde birbirine müdahale eden Threadların birbirlerine müdahale etmesi sonucu alınan hatayı irdelemiştik. Makaleyi detaylandırdığınızda anlayacağınız bir iş parçacığı içerisindeki işlevi farklı bir iş parçacığı içerisinde devreye sokuyorsak içerikteki ilgili hatayla karşılaşmaktayız.

İşte buradaki olası hata durumunun bir benzerini WPF uygulamalarında almaktayız. Birazdan yapacağımız örneklendirmede farklı iş parçacıklarının birbirlerine müdahale etmesi durumunda alınacak hata, yukarıda vermiş olduğum benzer içeriğe sahip adresteki hatayla farklı yöntem lakin aynı mantık çerçevesinde çözüme kavuşturulmaktadır.

Öncelikle aldığımız hatadan bahsederek başlayalım. Hatamızın metinsel halini aşağıda sunuyorum…

“System.InvalidOperationException: ‘The calling thread cannot access this object because a different thread owns it.'”

Hatamızın ekran görüntüsüde aşağıdaki gibidir,
WPF’te “The Calling Thread Cannot Access This Object Because A Different Thread Owns It” Hatası ve Çözümü
Bu hatanın Türkçe meali; “Başka bir iş parçacığına ait olduğundan çağıran iş parçacığı bu nesneye erişemiyor.” olacaktır. Yani anlayacağınız farklı Threadlar birbirlerine müdahale etmekte ve birine ait olan bir işlem başka birisi tarafından çağrılmaya/kullanılmaya/erişilmeye/çalıştırılmaya çalışılıyor.

Peki bu hatayı ne gibi durumlarda alıyoruz?

Hemen örneklendirelim…

        async void Say()
        {
            await Task.Run(() =>
            {
                int Sayac = 0;
                while (true)
                        lblSayac.Content = Sayac++;
            });
        }

        private void btnBaslat_Click(object sender, RoutedEventArgs e)
        {
            Say();
        }

Görüldüğü üzere Say metodu asenkron çalışmakta ve Name değeri “lblSayac” olan bir Label nesnesine müdahale etmektedir. Haliyle Say isimli Thread, içerisinde farklı bir Thread’a ait olan Label nesnesine erişmeye çalışmaktadır. İşte bu durumdan dolayı yukarıdaki olası hatayla karşılaşılmaktadır.

Hadi bu hatayı çözelim…

Yapmamız gereken aynen Windows Forms’larda olduğu gibi farklı Thread’da ki bir işlemi çağırmanın/kullanmanın/erişmenin/çalıştırmanın yolu ilgili işlemi o nesne üzerinde aşağıdaki gibi Invoke etmektir.

        async void Say()
        {
            await Task.Run(() =>
            {
                int Sayac = 0;
                while (true)
                    lblSayac.Dispatcher.Invoke(() =>
                    {
                        lblSayac.Content = Sayac++;
                    });
            });
        }

Dikkat ederseniz WPF’te Control nesnelerinin “Dispatcher” türünden propertysi mevcuttur. Bu tip, sıradaki işlemlere geçileceği durumlarda geçme işlemini sağlamaktadır. O yüzden de ‘sevk eden’ mahiyetinde bir anlamı vardır. İşte bu tipteki property aracılığıyla farklı kanaldaki bir işlev Invoke edilmekte ve konumuz olan ilgili hata ortadan kaldırılmaktadır.

Konumuzu sonlandırmadan önce Dispatcher sınıfıyla farklı bir yaklaşım sergileyerek ilgili olası hatamıza bir başka çözüm daha sunalım…

        async void Say()
        {
            await Task.Run(() =>
            {
                int Sayac = 0;
                while (true)
                    Dispatcher.Invoke(() => {
                        lblSayac.Content = Sayac++;
                    });
            });
        }

Gördüğünüz gibi kodumuz zahiren çok fazla değişkenlik göstermemiştir. Lakin Thread’lar da ki bu hata durumunu arındırmak için ilgili Control nesnesinin Dispatcher propertysini çağırabildiğimiz gibi, direkt olarak Dispatcher sınıfının static Invoke metoduylada işlemimizi gerçekleştirebiliriz.

Evet… Bir makalemizin daha sonuna gelmiş bulunmaktayız.
Umarım bol bol faydalanır, bu olası hatalardan projelerinizi arındırırsınız.

Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar dilerim…

Bunlar da hoşunuza gidebilir...

5 Cevaplar

  1. Hüseyin dedi ki:

    Çok teşekkürler Invoke olayını sizin sayenizde anladım!

  2. Halil dedi ki:

    Teşekkürler. Çözdüm gitti.

  3. mahir dedi ki:

    Ölmüşlerine rahmet, Allah razı olsun senden.

  4. Hakan dedi ki:

    Teşekkür ederim. Çok faydalı oldu gerçekten…

  5. Emaze dedi ki:

    Abi 2 saatir uğraşıyordum çözdüm saolasın

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir