19 Mayıs 2010 Çarşamba

c# thread ve işletim sistemi sorunsalları ve BackgroundWorker

main i dışına yolculuk ...

Selam,
tabiki burada işletim sistemleri felsefelerini inceleyemeyiz ama modern işletim sistemleri içerisinde c# ve windows ile multi thread nasıl kullanılır bunu küçük bi kaç örnekle açıklayabilriz.

Haydi başlayalım....

Herhangi bir programı çalıştırdığınızda CLR sizin için hali hazırda bir thread oluşturuyor.Yani aslında tüm programlarımız multi threaded ...

[STAThread]
static void Main()
{
...
[STAThread] ;
single-threaded Apartment - apartman yönetimi rejimi adını verdiğim sistem.
mingle , multi ; tek veya birden fazla birim çalıştırabiliyor olabiliyor.

Peki bu STAThread yaptık ne oldu ?
System.Windows.Forms içersindeki tiplerin geneli single-threaded apartment içerisinde çalışmak üzere dizayn edildiğinden dolayı win32 kullanıcı arabirimine ulaşırken karşılaşabileceğimiz olası iki sorunsaldan kurtulmuş olduk

bunlar ;
- kilitlenmenin(crash) önüne geçmiş olduk.
- genel işleyişin dışına çıkmasının önüne geçmiş olduk. darbe yapabilir neme lazım (nede olsa managed kod yazıyoruz değilmi )

Windows Forms ve WPF için BackgroundWorker sınıfını değerlendirmekte fayda var.
Durum bilgisi ve tamamlanma gibi bilgilere ihtiyaç duyulan thread leri gerektiği gibi yapabiliyor ve otomatik olarak gerektiğinde Control.Invoke veya Dispatcher.Invoke çağrılarını yapabiliyor.
Bu kadar bahsetmişken biraz ayrıntılarına girelim;

Worker threadlerde hata yönetimi zaten var yani try/catch lerle gerek kalmaz.
Durum değişikliklerinde/güncellemelerde Form elementlerini güncelleyebilir.
thread-pool kullanır böylece her işlem için tekrar tekrar thread oluşturulmaz.

using System;
using
System.Threading;
using
System.ComponentModel;
class Program {
static BackgroundWorker bw;

static void Main() {
bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += bw_DoWork;
bw.ProgressChanged += bw_ProgressChanged;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
    bw.RunWorkerAsync ("Merhaba, birim çalışmaya başladı...");    
    Console.WriteLine ("İptal için birkaç saniye içinde Enter tuşuna basın");
Console.ReadLine();
if (bw.IsBusy) bw.CancelAsync();
Console.ReadLine();
}
  static void bw_DoWork (object sender, DoWorkEventArgs e) {
    for (int i = 0; i <= 100; i += 20) {
if (bw.CancellationPending) {
e.Cancel = true;
return;
}
bw.ReportProgress (i);
Thread.Sleep (1000);
}
e.Result = 123; // RunWorkerCompleted tamamlandığında gönderilecek
}
 
  static void bw_RunWorkerCompleted (object sender,  RunWorkerCompletedEventArgs e) {
    if (e.Cancelled)
Console.WriteLine ("İptal Edildi!");
else if (e.Error != null)
Console.WriteLine ("Birim Hatası : " + e.Error.ToString());
else
Console.WriteLine ("Birim İşlem Tamam - " + e.Result); // DoWork tan gelecek 123 sonucu
}
  static void bw_ProgressChanged (object sender,  ProgressChangedEventArgs e) {
Console.WriteLine ("tamamlanma oranı " + e.ProgressPercentage + "%");
}
}

yukarıdaki kodun açıklamalarını ve kendi thread lerimizi yönetmeyi bi sonraki yazıya bırakıyorum.

görüşmek üzere
KANPINAR


Hiç yorum yok: