C# Dersleri 49 - Multithreading ve Thread Classı Kullanımı

     Yazılım dillerinde, birbirinden bağımsız iş parçacıklarının her birine Thread ismi verilir. C# dili ve daha doğrusu .Net ortamı, aynı anda birden fazla Thread kullanmamıza olanak sağlar, yani farklı işlemler için birden fazla Thread tanımlayabilir ve bunların aynı anda çalıştırılmasını sağlayabiliriz.

     Daha somut bir örnek vermek gerekirse; aynı anda hem sonsuz döngüde portları dinleyip gelen dataya göre gerekli işlemleri yapan, hem de belirli durumlarda email gönderen bir uygulama geliştirdiğinizi farzedin. Normal şartlarda uygulamanız mail göndermek için diğer işlemi ertelemek zorunda kalır. Yani uygulamanız mail gönderme işlemi bitene kadar port dinlemeyi bırakır. Bu da demek oluyor ki mail gönderme işlemi sırasında portlara gelen datayı kaçırırsınız. Ancak port dinlemek için ayrı, mail göndermek için ayrı bir Thread oluşturursanız; mail gönderme işlemi sırasında da bir yandan portları dinlemeye devam edebilirsiniz. Thread'ler bize bu multitasking işlevini kazandırır.

     Thread'ler CPU kullanımımızı düşürür ve kaynak kullanımını daha verimli hale getirir. Thread classı System.Threading kütüphanesi içindedir.

     C# Dilinde Aynı Anda Birden Fazla İşlem Yapma

     Bir Windows Form uygulaması oluşturalım. Bu form uygulamasında yalnızca bir button olacak ve tüm işlemimiz bu buttona tıklandığında gerçekleşecek.

     Aynı işlemi önce Thread kullanmadan yapacağım, daha sonra Thread kullanarak. Böylelikle aradaki farkı daha net görebileceğiz.

     Thread kullanmadan :     

private void btnClick_Click(object sender, EventArgs e)

    CountLonger();
    CountShorter();
}

public void CountLonger()
{
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(50);
    }
    MessageBox.Show("100'e kadar saydım");
}

public void CountShorter()
{
    for (int i = 0; i < 10; i++)
    {
        Thread.Sleep(50);
    }
    MessageBox.Show("10'a kadar saydım");
}

     Buttona tıklandığında 2 method çağırıyoruz. Bunlardan ilki CountLonger() methodu. Bu method 100'e kadar sayıyor ve sayma işlemi bittiğinde "100'e kadar saydım" yazan bir messagebox gösteriyor. Ayrıca sayma sırasındaki her adımda 50 milisaniye bekliyor. Thread.Sleep(50), uygulamamızın 50 milisaniye beklemesini sağlıyor. İkinci method ise CountShorter() methodu. Bu method yine 50'şer milisaniye bekleyerek 10'a kadar sayıyor ve bu işlemin sonunda "10'a kadar saydım" saydım şeklinde bir messagebox gösteriyor. Bu iki methodu bu örnekteki gibi button click eventinde çağırdığımızda önce CountLonger() methodu çalışmaya başlar. Bu method sonlanana kadar işlem devam eder. Daha sonra CountShorter() methodu çağırılır. Yani önce "100'e kadar saydım" mesajı gösterilir. Daha sonra "10'a kadar saydım" mesajı gösterilir. Şimdi de aynı işlemi Thread classını kullanarak yapalım :     

private void btnClick_Click(object sender, EventArgs e)
{
    Thread tlonger = new Thread(CountLonger);
    tlonger.Start();

    Thread tshorter = new Thread(CountShorter);
    tshorter.Start(); 
}

public void CountLonger()
{
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(50);
    }
    MessageBox.Show("100'e kadar saydım");
}

public void CountShorter()
{
    for (int i = 0; i < 10; i++)
    {
        Thread.Sleep(50);
    }
    MessageBox.Show("10'a kadar saydım");
}

     Bu sefer tLonger ve tShorter isminde iki Thread oluşturuyoruz. CountLonger() ve CountShorter() methodlarını bu iki thread aracılığıyla çağırıyoruz. Bu şekilde iki methodu aynı anda çalıştırmış oluyoruz, yani CountLonger() ve CountShorter() methodu aynı anda çalışmaya başlıyor. Dolayısıyla bu sefer ilk önce "10'a kadar saydım" mesajı gösteriliyor. Daha sonra "100'e kadar saydım" mesajı gösteriliyor. Gördüğünüz gibi CountLonger() methodu önce çağrılmış olmasına rağmen 2 method da çalışmaya başladı ve işlemi daha kısa süren CountShorter() methodu, diğer methodu beklemeden mesajı gösterebildi.

     Ayrıca belki farketmişsinizdir, ilk örnekte Windows Formu işlem bitene kadar dondu. İşlemler tamamlanana kadar butona tıklayamaz, formu sürükleyemez, hatta formu kapatamazsınız. Çünkü formun görüntülenmesini sağlayan Thread(yani main Thread) ile CountLonger() ve CountShorter() methodlarını çalıştıran Thread aynıydı. Dolayısıyla işlem tamamlanana kadar form da onları beklemek zorunda kaldı. Ancak ikinci örnekte bu methodlar için ayrı Thread oluşturunca formu da kullanmaya devam edebildik. Kullanıcı deneyimini düşünmek zorunda olduğunuzu bir uygulama geliştirdiğinizde çok önemli bir hal alacaktır bu konu. Çünkü arkadaki işlem bitene kadar arayüzün donması kullanıcıyı mutsuz edecektir.

     Bir Thread tanımlarken new Thread() kod cümlesinin içine bu Thread'in çalıştıracağı method ismi yazılır. Ancak dikkat edilmesi gereken nokta bu method void tipinde olmalı ve parametre almamalıdır. Daha sonra Thread classının Start() methodu ile bu Thread'in temsil ettiği methodu çağırmış oluruz.

     Thread Kullanırken Parametre Gönderme

     Gerçek projelerde kullandığımız çoğu method parametre kabul eder. Dolayısıyla Thread'lerle çalışırken de sıklıkla methodlara parametre göndermek isteriz. Şimdi örneği biraz değiştirelim. Bu sefer CountLonger() methodu 1 parametre alsın ve bu parametre for döngüsünde kaça kadar sayılacağını belirlesin. CountShorter() methodu ise 2 parametre alsın ve parametrelerden birisi for döngüsünün kaça kadar sayacağını belirlerken, diğer parametre de her bir adımda kaç milisaniye beklenmesi gerektiğini belirlesin.     

private void btnClick_Click(object sender, EventArgs e)
{
    Thread tLonger = new Thread(() => CountLonger(50));
    tLonger.Start();

    Thread tShorter = new Thread(() => CountShorter(10, 20));
    tShorter.Start(); 
}

public void CountLonger(int val)
{
    for (int i = 0; i < val; i++)
    {
        Thread.Sleep(50);
    }
    MessageBox.Show(val + "'e kadar saydım");
}

public void CountShorter(int val, int wait)
{
    for (int i = 0; i < val; i++)
    {
        Thread.Sleep(wait);
    }
    MessageBox.Show(val + "'a kadar saydım");
}

     Projeyi buradan indirebilirsiniz.

YORUMLAR
Email Adresi *
Görüntülenecek İsim *
Yorum *
Paylaş
  • f