Blog Kategorileri

Thread Nedir C#

C# dilinde bir thread, aynı anda birden fazla iş parçacığını yürütebilen ve bu sayede çoklu görevler gerçekleştirmeyi mümkün kılan bir yapıdır. Thread’ler, bir programın çeşitli bölümlerinin eşzamanlı olarak çalışmasını sağlar ve bu da genellikle performansı artırır veya kullanıcıya daha duyarlı bir deneyim sunar.

Thread’ler, işletim sistemi düzeyindeki iş parçacığı (thread) kavramına dayanır. Bu iş parçacıkları, CPU zaman dilimleri içinde çalışırlar ve aynı anda birden fazla thread çalışabilir. Bu nedenle, bir programın içinde birden fazla thread kullanarak farklı işlemleri eşzamanlı olarak gerçekleştirmek mümkündür.

C# dilinde thread’ler genellikle System.Threading namespace’i altında Thread sınıfı kullanılarak oluşturulur.

Thread kullanımı anlamak için aşağıdaki senaryomuzu ele alalım. Aşağıdaki programımızda Ürün Listeleme ve Raporlama için iki metot vardır. Kullanıcı menüden seçimini yaparak istediği ekranı açabilir. Lakin senkron bir programlama yapısı olduğundan dolayı programın şöyle bir handikabı vardır. Kullanıcı ekran seçimi yaptıktan sonra tekrar ekran seçim yapabilmek için tüm ürünlerin listelenmesi beklemek zorundadır.

namespace TutorialThreadFirst;

internal class Program
{
    static void Main(string[] args)
    {
        bool devamMi = true;
        while (devamMi)
        {
            Console.WriteLine("İşlem seçiniz:");
            Console.WriteLine("1-Ürünleri Listele, 2-Rapor Yazdır, 3-Çıkış");
            string Islem = Console.ReadLine();
            if (Islem == "1")
                UrunListele(); //Bu işlem seçildiğinde kaydetme işlemi bitinceye kadar menü gelmeyecektir.
            else if (Islem == "2")
                RaporYazdir();
            else if (Islem == "3")
                devamMi = false;
        }
    }
    static void UrunListele()
    {
        Console.WriteLine("Ürünler Listeleniyor...");
        for (int Sayac = 0; Sayac <= 1000; Sayac++)
        {
            Console.WriteLine("Ürünler - " + Sayac.ToString());
        }
        Console.WriteLine("Ürünler listelendi. Enter tuşuna basınız..");
        Console.ReadLine();
    }

    static void RaporYazdir()
    {
        Console.WriteLine("Rapor Yazdırılıyor...");
        for (int Sayac = 0; Sayac <= 1000; Sayac++)
        {
            Console.WriteLine("Rapor - " + Sayac.ToString());
        }

        Console.WriteLine("Rapo Yazdırıldı. Enter tuşuna basınız..");
        Console.ReadLine();
    }
}

Thread kullanıldığında ise, ürünlerin listelenmesi beklemeden menü tekrar kullanılabilir veya ürunler listelenirken eş zamanlı olarak rapor yazdırılabilir.

namespace TutorialThreadSecond
{
    internal class Program
    {
        static void Main(string[] args)
        {
            bool devamMi = true;
            while (devamMi)
            {
                Console.WriteLine("İşlem seçiniz:");
                Console.WriteLine("1-Ürünleri Listele, 2-Rapor Yazdır, 4-Tüm İşlemler, 5-Çıkış");
                string Islem = Console.ReadLine();
                if (Islem == "1")
                {
                    //Yeni bir thread oluştur: Bu satırda thread (iş parçacığı)'ın hangi metodu çağıracağı belirtilmiştir. 
                    Thread ThreadUrunListele = new Thread(new ThreadStart(UrunListele));

                    //Thread'i başlat: UrunListele metodunu çağırarak thread (iş parçacağının)'ın paralel çalışmasını sağlar.
                    ThreadUrunListele.Start();
                    //Ürünlerin Listelenmesinin bitirilmesi beklenmeden aşağıdaki kod parçacığının çalışmasına devam edilerek menü hemen gelecektir.
                }
                else if (Islem == "2")
                    RaporYazdir();
                else if (Islem == "3")
                    devamMi = false;
                else if (Islem == "4")
                {
                    Thread ThreadUrunListele = new Thread(new ThreadStart(UrunListele));
                    Thread ThreadRaporYazdir = new Thread(new ThreadStart(RaporYazdir));
                    ThreadUrunListele.Start();
                    ThreadRaporYazdir.Start();

                    //Ürünlerin Listelenmesi ve Rapor Yazdırılması paralel (eş zamanlı olarak) çalışacaktır.
                }
            }
        }
        static void UrunListele()
        {
            Console.WriteLine("Ürünler Listeleniyor...");
            for (int Sayac = 0; Sayac <= 1000; Sayac++)
            {
                Console.WriteLine("Ürünler - " + Sayac.ToString());
                Thread.Sleep(1000);
            }
            Console.WriteLine("Ürünler listelendi. Enter tuşuna basınız..");
            Console.ReadLine();
        }

        static void RaporYazdir()
        {
            Console.WriteLine("Rapor Yazdırılıyor...");
            for (int Sayac = 0; Sayac <= 1000; Sayac++)
            {
                Console.WriteLine("Rapor - " + Sayac.ToString());
                Thread.Sleep(1000);
            }

            Console.WriteLine("Rapo Yazdırıldı. Enter tuşuna basınız..");
            Console.ReadLine();
        }
    }
}

Thread Kavramları

Bu bölümde C# dilinde threading (thread yönetimi) konseptine giriş yaptık. Şimdi bu konu başlığı altında bilmeniz gereken bazı temel kavramları açıklayacağım:

Thread Oluşturma: Thread oluşturmak için Thread sınıfından bir örnek oluşturur ve Start metoduyla başlatırsınız.

Thread thread = new Thread(İşYapMetodu);
thread.Start();

Parametreli Thread Oluşturma: Thread’e parametre geçirmek istiyorsanız, ParameterizedThreadStart delegesi veya lambda ifadelerini kullanabilirsiniz:

Thread thread = new Thread(() => İşYapMetodu(parametre));
thread.Start();

Thread Senkronizasyonu: Birden fazla thread’in aynı anda paylaşılan kaynaklara erişmesi durumunda senkronizasyon önemlidir. lock anahtar kelimesi veya diğer senkronizasyon mekanizmalarıyla bu sağlanabilir.

object kilitlemeNesnesi = new object();

lock (kilitlemeNesnesi)
{
    // Paylaşılan kaynaklara erişim
}

Thread Bekletme (Join): Ana thread’in diğer thread’in tamamlanmasını beklemesi için Join yöntemi kullanılır. Bu, thread’ler arasında işlemlerin düzenlenmesini sağlar.

Thread thread = new Thread(İşYapMetodu);
thread.Start();
thread.Join(); // Diğer thread tamamlanana kadar bekler

Thread Kesme (Abort): Thread’i aniden durdurmak için Abort yöntemi kullanılabilir. Ancak, bu yöntem kullanıldığında bazı güvenlik riskleri ve beklenmedik sonuçlar olabilir. Bu nedenle, thread’leri güvenli bir şekilde sonlandırmak için diğer teknikler tercih edilir.

thread.Abort(); // Thread'i sonlandır

IsAlive: IsAlive özelliği, bir thread’in hala çalışıp çalışmadığını kontrol etmek için kullanılır. Thread çalışıyorsa true, değilse false döndürür.

if (thread.IsAlive)
{
    // Thread hala çalışıyor
}

Interrupt: Interrupt metodu, bir thread’in çalışmasını kesmek için kullanılır. Ancak bu metot genellikle kullanılmaz çünkü beklenmedik hatalara yol açabilir ve thread’in güvenli bir şekilde sonlanmasını zorlaştırabilir.

thread.Interrupt();

Sleep: Sleep metodu, belirtilen süre boyunca bir thread’i uyku moduna alır. Genellikle zamanlayıcı işlemler veya test senaryoları için kullanılır.

Thread.Sleep(1000); // 1 saniye uyku

Name Özelliği: Name özelliği, bir thread’in adını tanımlamak veya değiştirmek için kullanılır. Bu özellik, thread’leri daha kolay tanımlamak ve takip etmek için kullanışlıdır.

Thread thread = new Thread(İşYapMetodu);
thread.Name = "MyThread";

Priority Özelliği: Priority özelliği, bir thread’in öncelik seviyesini belirlemek için kullanılır. Öncelik seviyeleri ThreadPriority enum’u ile belirtilir (en yüksekten en düşüğe: Highest, AboveNormal, Normal, BelowNormal, Lowest).

thread.Priority = ThreadPriority.Highest;

Resume Metodu: Resume metodu, bir thread’i askıya alınmış durumdan (suspended) çalışır duruma getirmek için kullanılır. Ancak bu metot .NET Core 2.0 ve sonraki sürümlerde kullanılmamaktadır. Bunun yerine Monitor.Pulse veya Monitor.PulseAll gibi senkronizasyon mekanizmaları tercih edilir.

thread.Resume(); // Kullanılmamalı

Suspend Metodu: Suspend metodu, bir thread’i çalışır durumdan askıya almak için kullanılır. Ancak bu metot .NET Core 2.0 ve sonraki sürümlerde kullanılmamaktadır. Bunun yerine Monitor.Wait gibi senkronizasyon mekanizmaları tercih edilir.

thread.Suspend(); // Kullanılmamalı

Resume ve Suspend metotları .NET Core 2.0 ve sonraki sürümlerde kullanılmamaktadır çünkü thread’lerin kontrolünü doğrudan değiştirmek yerine daha güvenli ve doğru senkronizasyon mekanizmaları kullanılması tavsiye edilmektedir.

Thread ve Task Kavramları Arasındaki Farklar Nelerdir?

Thread ve Task, C# programlamada çoklu işlem yürütme yöntemleridir ancak aralarında bazı önemli farklar vardır.

Thread:

  • Thread, işletim sistemi seviyesinde gerçek bir işlemci iş parçacığıdır. Yani, bir thread doğrudan işletim sistemi tarafından yönetilir ve işlemci üzerinde bir görevi yürütür.
  • Thread’ler daha düşük seviyeli ve daha esnek bir kontrol sağlarlar. Ancak, bu kontrol ile gelen sorumluluklar (senkronizasyon, deadlock önleme vb.) daha fazla geliştirici dikkati gerektirir.
  • Thread’ler genellikle daha yüksek miktarda bellek ve işlemci kullanır.

Örnek Thread kullanımı:

Thread thread = new Thread(() =>
{
    // İşlemler
});
thread.Start();

Task:

  • Task, daha yüksek seviyeli bir soyutlamadır ve .NET tarafından sağlanan bir yapıdır (System.Threading.Tasks namespace).
  • Task’lar, thread’ler üzerinde çalışan bir soyutlamadır. Yani, bir task, bir thread üzerinde çalışabilir veya arka planda birden fazla thread kullanarak çalışabilir.
  • Task’lar daha kolay kullanım ve daha iyi optimize edilmiş kaynak yönetimi sunarlar. Özellikle async-await yapıları ile kullanıldığında, asenkron programlama için güçlü bir araçtır.
  • Task’lar genellikle daha az bellek ve işlemci kullanır çünkü sistem daha iyi kaynak yönetimini sağlar.

Örnek Task kullanımı:

Task task = Task.Run(() =>
{
    // İşlemler
});

Özetle, Thread daha düşük seviyeli ve doğrudan işletim sistemi üzerinde kontrol sağlarken, Task daha yüksek seviyeli soyutlama ve daha iyi kaynak yönetimi sunar. Task, modern C# uygulamalarında daha yaygın olarak tercih edilen bir yapıdır, özellikle asenkron programlama ve paralel işlemler için.

Last Updated : 03/05/2024

C# Birim Testleri için Mocking ve Moq’a Giriş

2023 © Coding, Developed by alkanfatih.com