Yazarlar Sözlük Makaleler Yardım Masası Gözlük Forum İstatistik

.NET ile threading


Özet
Threading kavramı ile daha önce tanışmadıysanız, programınız arka planda bir iş yaparken uygulama penceresinin kilitlendiğini ve ancak arka plandaki iş sona erdiğinde kullanıcıya tekrar cevap vermeye

Yazar Hakkında
Şehir :
Budapeste

Üyelik :
11 Ağustos 2005 16:24

Son Giriş :
12 Kasım 2007 00:55
» Mesaj gönder
» omeralmak hakkında
» Sözlükte omeralmak
.NET İle Threading
 
Bu yazıyı okuyan herkesin C# ile temel programcılık bilgisine sahip olduğunu varsayılmıştır.
 
Klasik Akış Mantığı
 
Threading kavramı ile daha önce tanışmadıysanız, programınız arka planda bir iş yaparken uygulama penceresinin kilitlendiğini ve ancak arka plandaki iş sona erdiğinde kullanıcıya tekrar cevap vermeye başladığını fark etmişsinizdir. Bunu neden yaşadığınızı hiç düşündünüz mü? Neden büyük firmaların yazdığı programlar kilitlenmiyor da bizimkiler kilitleniyor? Onlar C++ ve Assembly dillerini karıştırarak optimize edilmiş kodlar yazdığı için mi?
 
C++ ve Assembly ile yazılarak optimize edilmiş bir programın C# ile yazılmış bir programdan daha hızlı çalışacağı genelde doğrudur; ama arka planda zor bir işle uğraşan uygulamanın penceresinin kilitlenmesinin sebebi bu değildir.
 
Programcılık mantığı çerçevesinde, sadece birkaç tane program yazmış acemi bir programcının dahi kolayca fark edebileceği bir akış şekli vardır. Bu akış mantığında işlemci, program kodundan gelen komutları sırayla işler ve bir komut bitmeden bir diğer komuta geçmez.
 
Örneğin, ard arda iki tane fonksiyon çağıran basit bir program yazdığımızı varsayalım. 

 
Program önce birinci fonksiyonu çağırıp bitmesini bekleyecek, ve ancak birinci fonksiyon bittiğinde ikinci fonksiyonu çağıracaktır. Programımız; birinci fonksiyonun çalışması bitene kadar kullanıcıdan gelen komutlara cevap veremeyeceği gibi, ikinci fonksiyonu da başlatmayacaktır.
 
İkinci fonksiyon başladığında ise, işlem sonuçlanana kadar kullanıcı komutlarına yine cevap veremeyecektir.
 
Şimdi gelin, oldukça basit bir örnek ile söylediklerimizi hayata geçirelim.
 
static void Main(string[] args)
{
    // Fonksiyonları sırayla çağıralım
    f1();
    f2();
 
    // Pause
    Console.ReadLine();
}
 
public static void f1()
{
    for (int n = 0; n < 10; n++)
    {
        // Ekrana 1. fonksiyona ait sayıyı yazdırıp
        // programı 1 milisaniye bekletelim
        Console.WriteLine("1. Fonksiyon: " + n.ToString());
        Thread.Sleep(1);
    }
}
 
public static void f2()
{
    for (int n = 0; n < 10; n++)
    {
        // Ekrana 2. fonksiyona ait sayıyı yazdırıp
        // programı 1 milisaniye bekletelim
        Console.WriteLine("2. Fonksiyon: " + n.ToString());
        Thread.Sleep(1);
    }
}
 
Gördüğünüz gibi bu program, f1() ve f2() adlı iki fonksiyonu ard arda çağırmaktan başka hiçbir şey yapmıyor. Fonksiyonlarımız ise, ekrana kendi isimlerini ve 0-9 arasındaki sayıları sırayla yazdırıyorlar. Bu programı çalıştırdığımızda, ortaya nasıl bir sonuç çıkacağını tahmin etmek güç olmasa gerek.
 
Gördüğünüz gibi; programımız f1() fonksiyonunu çağırdıktan sonra, fonksiyon ekrana 0’dan 9’a kadar olan sayıları yazdırmış. f1() fonksiyonu sonuçlandıktan sonra f2() fonksiyonu devreye girmiş ve o da 0’dan 9’a kadar olan sayıları ekrana yazdırmış.
 
Buraya kadar herşey yolunda gözüküyor, öyle değil mi? Peki ya f1() fonksiyonu 0’dan 1.000.000.000’a kadar olan sayıları yazdırıyor olsa ve bu sırada programımız kullanıcıdan gelen komutlara cevap vermek durumunda kalsa? Program f1() fonksiyonu bitmeden hiçbir şey yapmayacağı için, klasik akış mantığı çerçevesinde bu problemin pratik ve verimli bir çözümü yoktur.
 
Tecrübeli C# programcıları, “f1() fonksiyonunun içine Application.DoEvents() diye bir komut ekleyerek bu problemi çözemez miyiz?” diye merak ediyor olabilir. Bu durumda, fonksiyonumuz şu hale gelirdi:
 
public static void f1()
{
    for (int n = 0; n < 10; n++)
    {
        // Ekrana 1. fonksiyona ait sayıyı yazdırıp
        // programı 1 milisaniye bekletelim
        Console.WriteLine("1. Fonksiyon: " + n.ToString());
        Thread.Sleep(1);
        Application.DoEvents();
    }
}
 
Eğer tek amacımız programın kullanıcıya cevap vermesini sağlamak ise; performanstan birazcık feragat edip böyle bir yöntem uygulayabiliriz.
 
Peki; ya f1() ve f2() fonksiyonlarının aynı anda çalışmasını istiyorsak ne yapacağız? Böyle bir durumda, Application.DoEvents() dahi bizi kurtaramaz.
 
Kurtaramaz ama, çözümsüz de değiliz tabii ki. Threading adı verilen teknik sayesinde; programımızın hem zor işlemler sırasında dahi kullanıcıya cevap vermesini sağlayabilir, hem de aynı anda birden fazla iş yapmasını sağlayabiliriz.
 
Thread Mantığı
 
Bildiğiniz gibi; Windows ve Linux gibi 32 bitlik işletim sistemlerinin neredeyse tamamı birden fazla işi aynı anda yapma yeteneğine sahiptir. Bu özellik sayesinde; MP3  dinlerken aynı anda E-Posta’larımızı kontrol edebilir, bir yandan Chat yaparken bir yandan yazı yazabiliriz.
 
“Threading” adı verilen bu özelliği kendi yazacağımız programlarda da kullanabiliriz desem ne düşünürdünüz? Ne düşünmeniz gerektiğini size söyleyeyim: Eğer bunu başarabilirsek; programımızın bir yandan zor bir işle uğraşırken bir yandan kullanıcı komutlarına cevap vermesini, veya iki fonksiyonu aynı anda çağırıp yürütmesini kolayca sağlayabiliriz.
 
Örnek programımıza geri dönelim. Threading tekniğinin nasıl kullanıldığını anlamak için, f1() ve f2() fonksiyonlarını bir arada yürütmeye çalışacağız. Bu durumda, akış şemamız aşağıdaki hale gelecektir:
 
Yazının en kritik noktasına gelmiş bulunuyoruz! Şimdi, yukarıdaki akış şemasının C# ile nasıl hayata geçirileceğini göreceğiz.
 
static void Main(string[] args)
{
    // Thread fonksiyonlarını tanımlayalım
    ThreadStart ts1 = new ThreadStart(f1);
    ThreadStart ts2 = new ThreadStart(f2);
 
    // Thread'ları tanımlayalım
    Thread t1 = new Thread(ts1);
    Thread t2 = new Thread(ts2);
 
    // Thread'ları başlatalım
    t1.Start();
    t2.Start();
 
    // Pause
    Console.ReadLine();
}

public static void f1()
{
    for (int n = 0; n < 10; n++)
    {
        // Ekrana 1. fonksiyona ait sayıyı yazdırıp
        // Thread'i 1 milisaniye bekletelim
        Console.WriteLine("1. Fonksiyon: " + n.ToString());
        Thread.Sleep(1);
    }
}

public static void f2()
{
    for (int n = 0; n < 10; n++)
    {
        // Ekrana 2. fonksiyona ait sayıyı yazdırıp
        // Thread'i 1 milisaniye bekletelim
        Console.WriteLine("2. Fonksiyon: " + n.ToString());
        Thread.Sleep(1);
    }
}
 
Gördüğünüz gibi; Threading mantığını hayata geçirmek için 3 temel adım attık:
f1() ve f2 () fonksiyonlarını birer ThreadStart haline getirdik. ThreadStart’lardan faydalanarak, t1 ve t2 adında birer Thread yarattık. Thread’ları başlattık.
 
Programı bu haliyle çalıştırdığımızda ortaya çıkacak olan sonucu merak ediyorsunuz, öyle değil mi? Buyrun görelim o halde...
 
Programın ürettiği çıktıya dikkat edin! Klasik akış mantığında program, f1() fonksiyonunun yaptığı işi bitirmeden f2() fonksiyonuna geçmiyordu. Threading mantığında ise; f1() ve f2() fonksiyonlarının yaptıkları işler paralel bir şekilde işlenmiş. Yani iki fonksiyon aynı anda yürütülmüş.
 
Programınız zor bir işle uğraşırken kullanıcı komutlarına cevap vermesini nasıl sağlayabileceğinizi bu noktada anladığınızı tahmin ediyorum. Yapılması gereken şey, söz konusu “zor iş”e ait fonksiyonu doğrudan doğruya çağırmak yerine bir Thread haline getirmekten ibaret! Bir programa iki işi aynı anda nasıl yaptırabileceğimizi ise yukarıdaki basit örnekte açık bir şekilde görmüş olduk.
 
Kendimizi tebrik edebiliriz!
 
Sonuç
 
Bu yazıda, .NET platformunda Thread mantığıyla nasıl programlama yapılacağını ve bu şekilde programlarımıza birden fazla işin aynı anda nasıl yaptırılabileceğini öğrenmiş olduk. Thread konusuna ilgi duyuyorsanız ve daha derin bir araştırma yapmak isterseniz, ek kaynaklar bölümündeki siteleri ziyaret etmenizi tavsiye ederim. Bunun yanı sıra; bu yazıdaki temel Thread mantığı anladıktan sonra aşağıdaki anahtar kelimelerin peşinden gidip kendinizi biraz daha geliştirebilirsiniz:
Timeout kavramı Thread sınıfının Abort, Join, Resume, Suspend komutları ThreadPriority kavramı ThreadPool sınıfı
 




Yorumlar

1.  çok teşekür ederim. bende programım mail atarken işlemlere nasıl devam ederim diye düşünüyordum.web uygulamalırında kullanıcının beklememesi esası düşünüldüğünde harika bişi bu thread.
cetinz
11 Ekim 2005 01:30
Bu konuda bildiklerinizi bizlerle paylaşabilirsiniz
Tabi bunun için yazarsanız giriş yapmalı, yazar değilseniz yazar olmalısınız.
© 2005, Bilişim Kulübü. (1046 ms)
Ne yapabilirsin: SubtitleClick ile İngilizceni Geliştir, Çınar Framework ile kod yaz, Eglencelik.org'ta biraz eğlen