22 Nisan 2012 Pazar

C# 'da BackgroundWorker Detay

Merhaba arkadaşlar...
Bu yazım "kontrolü" makalemin devamı niteliğinde olacaktır, aynı örnek üzerinden eklemeler oolacaktır. Fakat daha detaylı inceleyeceğiz. BackgroundWorker 'ın "DoWork" event 'ine parametre göndereceğiz. Bunun için BackgroundWorker 'ı çalıştırdığım kod satırında BackgroundWorker 'ın "RunWorkerAsync" metodunun diğer "overload" 'ını kullanacağız. Benden object tipinde bir tane parametre ister, istediğim nesneyi gönderebilirim. Bunu görmek için formuma bir adet TextBox atıyorum. "RunWorkerAsync" metodumu çalıştırdığım yerde TextBox 'tan aldığım değeri "RunWorkerAsync" metoduma parametre olarak veriyorum.

        public Form1()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
        }
        private void btnIsYap_Click(object sender, EventArgs e)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(textBox1.Text))
                {
                    int i = int.Parse(textBox1.Text);
                    backgroundWorker1.RunWorkerAsync(i);
                    //i object 'e çevrildi (boxing)
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Sayısal değer giriniz..");
            }
        }
"DoWork" event 'ine gelen arguman "e.Argument" ile alınır. Bu değer bizim ProgressBar kontrolünün maximum değeri olmalıdır. For döngüm bu değer kadar dönmeli ve bu sayıya kadar olan sayıları toplamasını isteyelim.

BackgroundWorker 'ın, "WorkerSupportsCancellation" özelliğini "true" yapmalıyım ki, uygulama çalışmasını sürdürürken, kullanıcı istediği zaman uygulamadan çıkabilsin. , Kullanıcının cancel yapıp yapmadığını da "DoWork" metodunda kontrol etmeliyim. Tek çekirdekli işlemciler "multi progress" çalışamaz. Yani aynı anda tek bir işlem yapabilirler. Birden fazla işlem yapması istenirse bu işlemleri sıraya koyar ve birinden bir parça diğerinden bir parça yapar. Bu işlemi de çok hızlı yaptığından dolayı işlemci, bize aynı anda birden fazla işlem yapıyormuş gibi görünür. Kullanıcının cancel işlemi yapıp yapmadığını, BackgroundWorker 'ın bool dönen, CancellationPending adındaki property 'si sayesinde kontrol edebilirim. Eğer BackgroundWorker 'ın kullandığı bu thread için bekleyen bir cancel işlemi varsa metot bize true dönecektir. Biz de "e.Cancel = true" yapacağız ve döngüden çıkacağız. Daha sonra kullanıcının uygulamayı cancel edebilmesi için btnDurdur_Click event 'inde backgroundWorker1.CancelAsync() metotunu çağırmam gerekiyor.

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            long toplam = 0;
            int j = int.Parse(e.Argument.ToString()); //i int'e çevrildi(unboxing) 
            for (int i = 0; i <= j; i++)
            {
                if (backgroundWorker1.CancellationPending)
                {
                    e.Cancel = true;
                    break;
                }
                toplam += i;
                this.Text = i.ToString();
                backgroundWorker1.ReportProgress(i / (j/100));
                System.Threading.Thread.Sleep(100);
            }
            e.Result = toplam.ToString();
        }
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                MessageBox.Show("İptal edildi..");
                progressBar1.Value = 0;
            }
            else
                MessageBox.Show(e.Result.ToString());
        }

        private void btnDurdur_Click(object sender, EventArgs e)
        {
            backgroundWorker1.CancelAsync();
            textBox1.Text = string.Empty;
            this.Text = 0.ToString();
        }

Daha sonra backgroundWorker1_RunWorkerCompleted event 'inde, eğer kullanıcı cancel ile çıkmışsa (e.Cancelled==true) ekrana bir mesaj vermesini istedim. Yok eğer kullanıcı çıkmadı ve işlem tamamlandıysa sonucu (e.Result) ekrana vermesini istedim. "e.Result", DoWorkEventArgs argumanın bir özelliğidir. e.Result 'i ben backgroundWorker1_DoWork event 'inden object olarak gönderdiğimden dolayı, backgroundWorker1_RunWorkerCompleted event 'inde, ekrana yazdırmak için string tipine çevirmeliyim.


Başka bir yazıda görüşmek dileğiyle, hoşçakalın...

Hiç yorum yok:

Yorum Gönder