26/11/2015 21

C# ile Multi Thread Çalışma -- Çok Kanallı Çalışma

Herkese merhabalar. Bu yazıda sizlere C# ile nasıl multi Thread çalışmayı anlatacağım. İlk olarak Multi Thread ne demektir onu anlatacağım.

Multi thread çok kanallı çalışma anlamına gelir. yani yapılacak olan bir işlemi parçalara bölüp aynı anda kaç parçaya böldüysek yapmaktır. İşçi havuz problemlerindeki gibi bir işi tek bir işçi yapacağına birden fazla işçinin yapmasını sağlayacağız.

Bu şekilde işlemlerimiz iki kat üç kat hızlanacaktır. Çünkü birden fazla işlem parrçacığı ile işlem yapmış olacağız.

Bu işlem için programımıza ilk olarak Thread kütüphanesini eklememiz gerekmektedir.

using System.Threading;
using System.Threading.Tasks;

Yukarıdaki kütüphaneleri ekledikten sonra kodlama kısmına geçebiliriz. İlk olarak thread ile çalışacak fonksiyonlarımızı belirtmeliyiz. Yani thread çalıştırıldığında hangi fonksiyonumuz çalışacak bunu hazırlamamız gerekmektedir.


 public void say1()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i.ToString());
            }
        }

        public void say2()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i.ToString());
            }
        }

        public void say3()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i.ToString());
            }
        }

Yukarıdaki gibi üç tane fonksiyon hazırladık ve ve bu fonksiyonları ayrı ayrı thread lar ile çağıracağız ve çıktılara bakacağız. Program çıktısından threadların işlemi yapma şekline bakacağız. Şimdi Threadların nasıl çalıştırıldığına bakalım...


Thread tread1= new Thread(say1);
      treat1.Start();

      Thread tread2= new Thread(say2);
      tread2.Start();

      Thread tread3= new Thread(say3);
      tread3.Start();

Yukarıdaki kod bloğunda ise Threadlarımızı oluşturduk ve başlattık. Gördüğümüz gibi threadlarımız oluşturduk ve içerisinde hangi fonksiyonun çalışacağını belirledik Bu şekilde fonksiyonu thread üzerine bindirdik ve çalıştırdık.


1
2
1
2
3
4
1
2
6
7
3
4
5
Gerisi getirmedim. Gördüğünüz gibi threatların çalışma sırasına göre farklı Çıktılar alabiliyoruz.

Peki Threadların içerisinde aynı fonksiyonu çalıştıramazmıyız.

Tabiikide çalıştırabiliriz. Farklı Threadlar içerisinde aynı fonksiyonu çalıştırabiliriz.Aşağıda bununla ilgili bir örnek yapalım.

 void islem()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i.ToString());
            }
        }


        Thread tread1 = new Thread(islem);
        tread1.Start();

        Thread tread2 = new Thread(islem);
        tread2.Start();

        Thread tread3 = new Thread(islem);
        tread3.Start();

Yukarıdaki kod bloğunda gördüğümüz üzere aynı fonksiyonu üç farklı thread ile üç defa çalıştırmış olduk. Bu şekilde fonksiyonun yapacağı toplam işi üçe bölerek yaptırmış olduk ve işlemi daha hızlı bir şekilde yaptırmış olduk. Programın çıktısı yine önceki örneğin çıktısına benzer olacaktır.

Birde dikkat edersek fonksiyonun içerisine değişken değeri göndermeden bu işlemi yaptık. Ama atıyorum 300.000 tane değişken değeri olacak olan bir sonuç almak istiyoruz. Peki bunu nasıl yapacağız. Yukarıdaki şekilde dikkat edin değişkenlerimizi Thread ile fonksiyona gönderemiyoruz.

Aşağıda yazacağımız fonksiyon örneği ile fonksiyon içerisine değişken göndererek çalıştıralım.

 void fonksiyon(int bas,int son)
        {
            for (int i = bas; i < son; i++)
            {
               Console.WriteLine(i.ToString());
            }
        }

        Thread tread1 = new Thread(() => fonksiyon(0,10));
        tread1.Start();

        Thread tread2 = new Thread(() => fonksiyon(10,20));
        tread2.Start();

Yukarıdaki örnekte fonksiyon içerisine değişken gönderdir. Değişken göndererek çalışmasını sağladık. Programın çıktısı ise yaklaşık olarak aşağıdaki şekilde olacaktır.


1
2
10
11
12
3
14
4

Yukarıdaki programın çıktısının geri kalanını yazmadım ama aşağı yukarı bu şekilde çıkacaktır. Birde farklı bir yöntem olarak delegate nesnelerini kullanarak başlatma var. Yani kodlarımızı bir delegate ye eşitliyoruz ve o şekilde çalıştırıyoruz Aşağıda ise bunun ile ilgili bir örnek verdim onuda inceleyelim


ThreadStart ts = delegate
{
      for (int i=0; i<10; i++)
      {
           for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i.ToString());
            }
           //kodlar buraya gelecek bu şekildede fonksiyonumuzu buraya yazarak çalıştırabiliriz
      }
};
new Thread(ts).Start();

Eğer isterseniz şimdi son bir örnek yapalım ve yazımızı bitirelim.

Şimdi girilen bir sayıya kadar olan çift sayıları bulduran bir programı multi thread mantığı ile yapalım.

int sayac = 0;
int girilen = Convert.ToInt32(Console.ReadLine());


        void kontrol(int bas,int son) //kontrol edecek olan fonksiyonumuz
        {
            for (int i = bas; i < son; i++)
            {
                if (i % 2 == 0)
                {
                    sayac++;
                    Console.WriteLine(i.ToString());
                }
            }
        }

        int thread_sayisi = girilen / 1000 + 1;

        for (int i = 0; i < thread_sayisi; i++)
                {
                    Thread treat = new Thread(() => kontrol(thread_sayisi*i,thread_sayisi*(i+1));
                    treat.Start();
                }

Yukarıda thread_sayisi ile sayıları biner biner kontrol ettireceğiz kaç tane sayı giriyorsa onu 1000 sayısına bölecek ve işlemi o kadar thread ile yaptıracak. For döngüsü içerisinde yukarıdaki gibi fonksiyonlarıda yazabiliriz.

Göründüğü gibi for döngüsü içerisinde istediğimiz kadar thread oluşturduk ve başlattık. Bu şekilde işlem hızını kulanıcının girdiği değere göre yaptırdık. Bu şekildede normal olarak yaptığımızda 10 saniyede bitecekse işlem 2 , 3 saniyeye kadar indirdik.

Son olarak şunuda ekleyerek yazımızı bitirelim

Bir elin nesi var iki elin sesi var mantığı ile Multi Thread kulanımı programlarımızda ağır işlemler için çok büyük hız kazanmamıza yardımcı olacaktır. Çünkü aynı işlemi birden çok işçiye yaptırmış oluyoruz.

Bu yazımızda bu kadar -- Takipte Kalın

İyi Çalışmalar

Burak Hamdi Tufan


Tags

Share this Post



Post a Comment

Success! Your comment sent to post. It will be showed after confirmation.
Error! There was an error sending your comment.

Comments

  • MUSTAFA BÜKÜLMEZ

    Selamlar, Çok sadece ve güzel anlatmışsınız bunu için çok teşekkür ederim. Size bir sorum olacaktı bu konu ile ilgili olarak. Şuanda yürüttüğüm bir asp.net web projem var ve işlemlerin %80 sql üzerinden çalışıyor. Sayfalarda hep fonksiyonlarım var onların içlerinde başka fonksiyonlar (sql fonksiyonları) bu sebepten dolayı özellikle bir sayfamdaki devexress grid çok yavaş geliyor. İlgili fonksiyonu sqlde çalıştırdığımda veri 2-3 saniyede geliyor fakat gride doldururken sayfanın açılması 15 20 saniyeyi buluyor. Şuan maksimum 3 kişi ile aynı anda test ettim. 3 kişi aynı anda sayfaya tıkladığında sayfa bile açılmıyor. Olur mu bilmiyorum fakat bu thread'ları asp.net te de gridviewin hızlı doldurulması için kullanabilir miyiz? Kullanabilmemiz mümkünse nasıl kullanabiliriz?

    2015/11/26 13:18:08
    • Burak Hamdi TUFAN

      Evet kullanılabilir Fakat sitenizdeki veritabanı kodları SQL den gelirken tabloları dolduruyorken onu tek bir fonksiyon ile yapar. ama atıyorum tablonun yarısını bir fonksiyon diğer yarısını bir fonksiyon ile doldurmayı düşünüyorsanız olabilir. Sitelerinizdeki sql işlemleri için benim önerim Linq To Sql Kullanımıdır. Tablo doldurma ekleme silme gibi işlemler çok hızlı ilerler. Ayrıca sorgunuzun dönmesi nasıl çalıştığınada bağlıdır. yani gereksiz değişkenler gönderiyorsanız veya çekiyorsanız yine yavaş gelir. Birde yavaşlığın sebebi hosting sağlayıcınızda olabilir. İyi çalışmalar dilerim

      2015/11/26 13:37:25
  • Murat

    Multithead ile proses içerisinde asenkron programlama arasında bir fark var mıdır ?

    2017/11/27 15:52:48
    • Burak Hamdi TUFAN

      Çok bir fark olduğunu sanmıyorum. Fakat process thread yerine threadpool kullanmak daha etkili olabiliyor. Bu arayüzü tarafından gerekebiliyor.

      2018/02/02 10:28:34