Thread(İplik) Kavramı ve Kullanımı

Eyl 08, 2013
Thread (İplik) işlemleri
İşletim sistemleri adlandırılmasında (terminoloji) çalışmakta olan programlara süreç (process) denilmektedir. İplikler süreçlerin farklı çizelgelenen akışlarıdır. Windows sistemleri iplik temelinde çizelgeleme yapmaktadır. İşletim sistemi tüm süreçlerin ipliklerini bir çizelgede tutmakta ve bunları zaman paylaşımlı olarak çalıştırılmaktadır. Bir thread biraz çalıştırılmakta sonra çalışmasına ara verilmektedir. Başka bir thread kalınan yerden çalışmaya devam ettirilmektedir. Programcı kendi ipliğinin kesiksiz çalıştığını sanabilir fakat aslında akış parçalı olarak çalıştırılmaktadır.

Örneğin işletim sistemi P1 sürecinin T1 ipliğini 20ms kadar çalıştırmakta sonra kalınan yeri saklamaktadır, bu kez P1 sürecinin T2 ipliğine geçmektedir. Sonra aynı biçimde P2 sürecinin ve P3 sürecinin iplikleri çalıştırılmaktadır. Yeniden başa dönülüp işlem devam etmektedir. Birden fazla mikroişlemci bulunan sistemlerde (IntelDualCore), işletim sistemi her işlemci için ayrı bir çizelge oluşturup daha hızlı bir çalışma sağlamaktadır. İşletim sistemi ,işlemcilere iplikleri atamaktadır.

İplik’lerin yaratılması
İpliklere ilişkin sınıfların büyük çoğunluğu System.Threading isim alanı içerisindedir.  Her süreç çalışmaya bir iplik ile başlamaktadır. Bu ipliğe sürecin ana ipliği (Main Thread) denilmektedir. Yeni bir iplik yaratmak için Thread isimli sınıf kullanılmaktadır. Bu sınıfın başlangıç fonksiyonunda iplik akışının başlatılacağı fonksiyon belirtilip,  nesne yaratıldıktan sonra sınıfın Start() üye fonksiyonu ile iplik çalıştırılmaktadır. Thread sınıfının başlangıç fonksiyonlarından biri şöyledir:
public Thread (ThreadStart start)

ThreadStart isimli temsilci (delege) şöyledir:
public delegate void ThreadStart( )

Bu durumda Thread fonksiyonu olarak geri dönüş değeri void olan parametresiz bir fonksiyon verilmektedir. Thread fonksiyonu bir sınıfın "static" olan ya da "static olmayan" bir fonksiyonu olabilmektedir.

static void Main() 

     Thread t = new Thread(new ThreadStart(ThreadProc)); 
     t.Start(); 
}

public static void ThreadProc() { }


Bir iplik herhangi bir iplik akışı içerisinde yaratılabilmektedir. Yani ana iplikte yaratılması gibi bir zorunluluk yoktur. Sürecin ana ipliğin diğer yaratılmış olan ipliklerden hiçbir farkı yoktur, yani herhangi bir iplik için söz konusu olan her şey ana iplik için de aynıdır. İplik bir fonksiyon değil akış belirtmektedir. Örneğin iki iplik akışı aynı fonksiyon üzerinde ilerleyebilmektedir. Thread sınıfının static Sleep fonksiyonları belirtilen milisaniye kadar fonksiyonu çağıran ipliği bloke ederek bekletmektedir.

public static void Main()
{
    Thread t = new Thread(new ThreadStart(ThreadProc));
    t.Start();
    for (int i = 0; i < 10; ++i)
    {
        Console.WriteLine("Main thread: {0}", i.ToString());
        Thread.Sleep(1000);
    }
}

public static void ThreadProc()
{
     for (int i = 0; i < 10; ++i)
     {
         Console.WriteLine("Other thread: {0}", i.ToString());
         Thread.Sleep(500);
     }
}


Bir İplik'in sonlanmasının beklenmesi
Bazen bir iplik, bir işin belirli bir kısmını yapmak için oluşturulmaktadır. Başka bir iplik ise o iplik sonlanana kadar beklemektedir. Bekleme işlemi Thread sınıfının Join () fonksiyonları ile yapılmaktadır.

public void Join ( )

Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));           t.Start("Sample");
t.Join();
Console.WriteLine("Thread sonlandi!..");

"Join" fonksiyonlarının "int" parametreli ve "TimeSpan" parametreli versiyonları da vardır. Bu parametreler zaman aşımı (Timeout) parametreleridir. Join fonksiyonu iplik bitene kadar ya da en kötü olasılıkla belirtilen zaman aşımı dolana kadar bekleme yapmaktadır. Örneğin:

public bool Join (int millisecondsTimeout)

t.Join(1000);

Burada iplik bitene kadar ya da bir saniye (1000 milisaniye) geçene kadar bekleme yapılmaktadır. Birden fazla ipliği beklemek için birden fazla Join işlemi uygulamak gerekmektedir. Join fonksiyonlarının geri dönüş değeri "bool" türdendir. Eğer Join ipliğin bitmesinden dolayı sonlanmış ise fonksiyon "True" değeri ile, zaman aşımından dolayı sonlanmış ise fonksiyon "False" değeri ile dönmektedir.

İpliklerin sonlanması
Bir iplik çeşitli biçimlerde sonlanabilmektedir. En doğal sonlanma Thread fonksiyonunun bitmesi ile oluşmaktadır. "Environment" sınıfının "Exit" fonksiyonu süreci tüm iplikleri ile birlikte sonlandırmaktadır.

Environment.Exit(0);

Bir ipliği arka plana geçirmek için Thread nesnesinin "bool" türden "IsBackground" özelliğine (property) "True" değeri atamak gerekmektedir. Bir iplik başka bir ipliği "Abort" fonksiyonu ile sonlandırabilir.

public static void Main()
{
    Thread t= new Thread(new ParameterizedThreadStart(ThreadProc));
    t.Start("other");
    Console.ReadLine();
    t.Abort();
    Console.WriteLine("Thread Sonlandirildi!..");
    Console.ReadLine();
}

public static void ThreadProc(object o)
{
    string s = (string)o;
    try
    {
        for (int i = 0; ; ++i)
        {
            Thread.Sleep(500);
            Console.WriteLine("{0}:{1}", s, i.ToString());
        }
    }
    catch (Exception e)
        Console.WriteLine("Exception handled!..");
    Console.WriteLine("Thread bitiyor");
}