Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

UI Donmasın Diye DoEvents'e Döndüm, Sonra Pişman Oldum!

websterx

Üye
Katılım
14 Mart 2026
Mesajlar
9
🤯 UI Donunca Panik ve İlkel Çözüm

Dostlar, kafayı yiyecektim. Şu an üzerinde uğraştığım masaüstü uygulamasında (WinForms, tabii ki) uzun süren bir veri işleme döngüsü var. Kullanıcı "İşlemi Başlat"a basıyor, benim kod arka planda koca bir List<T>'yi dönüp duruyor ve arayüz tamamen donuyor. "İptal" butonu bile tıklanmıyor, mouse işareti saat simgesine dönüyor. Klasik.

StackOverflow'da bile "UI responsive tutmak" diye aratınca, ilk çıkan cevaplardan biri, o meşhur ve tehlikeli yöntem: Application.DoEvents(). "Şuraya bir tane koyayım, döngüde her adımda UI'ın nefes almasını sağlar" diye düşündüm. Ve evet, çalıştı!

C#:
for (int i = 0; i < devListe.Count; i++)
{
    // Uzun süren işlem...
    VeriyiIsle(devListe[i]);

    // İlkel çözüm! UI'ı tazele.
    Application.DoEvents();
}

Arayüz artık donmuyordu, progress bar ilerliyordu, hatta iptal butonuna basılabiliyordu. Mutluluk.

⚠️ Meğerse Kediye Ciğer Satmışım

Ta ki, kullanıcının işlem devam ederken arayüzdeki başka bir butona hızlıca tıklayabileceği aklıma gelene kadar. Şaka gibi ama, DoEvents() o tıklama olayını da işliyor! Yani, uzun süren işlemin ortasında, başka bir event handler'ı tetiklenebiliyor. Bu da, paylaşılan kaynaklara (aynı listeye, aynı değişkene) aynı anda erişim denemesi demek.

Sonuç? NullReferenceException, garip davranışlar, bazen de tamamen çöküş. Debug ederken olayların sırasını takip etmek imkansız hale geldi. Kod, re-entrancy (tekrar giriş) denen canavara dönüştü. Sanki tek bir iş parçacığında iki farklı kod aynı anda koşmaya çalışıyor gibiydi.

💡 Doğru Yola Geri Dönüş: BackgroundWorker ve Task

Neyse ki, eski günahlarımdan döndüm. WinForms dünyasında bunun için güvenli yollar var. Eski dostum BackgroundWorker veya daha modern yaklaşım Task.Run() ile async/await.

İşte basit bir Task.Run() örneği:

C#:
private async void btnIslemiBaslat_Click(object sender, EventArgs e)
{
    btnIslemiBaslat.Enabled = false;
    progressBar1.Visible = true;

    await Task.Run(() =>
    {
        for (int i = 0; i < devListe.Count; i++)
        {
            // Uzun süren işlem UI thread'ini bloklamaz!
            VeriyiIsle(devListe[i]);

            // Progress bar'ı güncellemek için Invoke kullan.
            progressBar1.Invoke(new Action(() => { progressBar1.Value = (i  100) / devListe.Count; }));
        }
    });

    // İşlem bitti, UI'ı eski haline getir.
    progressBar1.Visible = false;
    btnIslemiBaslat.Enabled = true;
}

Bu yöntemde, uzun işlem arka planda bir thread'de koşarken, UI thread'i (ana thread) serbest kalıyor ve kullanıcı etkileşimlerine cevap verebiliyor. İptal butonu için CancellationToken kullanmak da mümkün.

Sonuç olarak, DoEvents() hızlı bir fix gibi görünse de, aslında koduna istemediğin karmaşıklıklar ve bug'lar ekleyen bir tuzak. Ben bu tuzağa düştüm, siz düşmeyin. Acil durumlarda bile kullanmadan önce iki kere düşünün.

Peki ya siz? Hiç DoEvents() kullanıp sonradan başınızı duvarlara vurduğunuz oldu mu? Ya da WinForms/WPF'te UI'ı responsive tutmak için favori, temiz yönteminiz nedir?
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Geri