İş Parçacıkları Thread(s)
Bir çok geliştirici programlarını doğrusal(linear) bir şekilde oluşturmaktadır. Böyle bir durumda tek bir processin işini bitirmesi beklenmekte ve ardından bir sonraki kod parçasına geçilmektedir. Günümüzde ise bu şekilde(tek process tek thread) olduğu yaklaşım sınırlılıklara sahiptir.
İş Parçacığı (Thread) İş parçacığı, processin en küçük yürütme birimidir. Bir processin çok sayıda threadi olabilir. Her bir thread farklı bir işlemcide veya işlemcinin çekirdeğinde icra edilebilir.
Çoklu İş Parçacıkları (Multiple Threads) Bir çok metodu arka planda System.Threading namespace’ini kullanarak çalıştırmak mümkündür. Bu isim alanı içerisinde kullanılan metot ise “ThreadPool.QueueUserWorkItem” dır.
Thread Havuzu (ThreadPool) class Program { static void Main(string[] args) ThreadPool.QueueUserWorkItem(ThreadProc); Console.WriteLine("Ana thread işlem yapıyor ve ardından uyumakta"); Thread.Sleep(5000); Console.WriteLine("Ana threadten çıkılıyor"); } static void ThreadProc(object stateinfo) Console.WriteLine("Thread çalışıyor");
class Program { static void Main(string[] args) string state = "Merhaba Bilgisayar Mühendisliği“; ThreadPool.QueueUserWorkItem(ThreadProc,state); Console.WriteLine("Ana thread işlem yapıyor ve ardından uyumakta"); Thread.Sleep(5000); Console.WriteLine("Ana threadten çıkılıyor"); } static void ThreadProc(object stateinfo) Console.WriteLine("Gelen ifade:"+stateinfo.ToString());
Eğer threadlerin eş zamanlı olarak çalışması gerekiyorsa, ThreadPool Eğer threadlerin eş zamanlı olarak çalışması gerekiyorsa, ThreadPool.QueueUserWorkItem metodu bir çok defa çağrılabilir. ThreadPool.QueueUserWorkItem(ThreadProc, “Thread 1”); ThreadPool.QueueUserWorkItem(ThreadProc, “Thread 2”); ThreadPool.QueueUserWorkItem(ThreadProc, “Thread 3”); ThreadPool.QueueUserWorkItem(ThreadProc, “Thread 4”); Thread havuzunda varsayılan olarak, işlemci başına maksimum 250 çalışan thread bulunabilir.
Background & Foreground Threadler Ana uygulama her zaman için önplandaki (foreground) thread’dir. Ön plandaki thread aktif olduğu sürece, uygulama çalışmaya devam eder. Arkaplandaki threadler, ön plandaki threadler çalışmalarını bitirince çalışmalarını sonlandırırlar.
IsBackground : Bu özellik sayesinde thread’in arka planda çalışan bir thread olup olmadığı kontrol edilebilir.
class Program { static void Main(string[] args) { ThreadPool class Program { static void Main(string[] args) { ThreadPool.QueueUserWorkItem(ThreadProc,"Thread 1"); ThreadPool.QueueUserWorkItem(ThreadProc, "Thread 2"); ThreadProc("Thread 3"); ThreadPool.QueueUserWorkItem(ThreadProc, "Thread 4"); Console.WriteLine("Ana thread çalışmakta ardından uyumakta"); Thread.Sleep(5000); Console.WriteLine("Ana threadten çıkılıyor"); } static void ThreadProc(object stateinfo) { string state = (string)stateinfo; if (Thread.CurrentThread.IsBackground == true) Console.WriteLine("Arkaplan threadinden merhaba"+state); else Console.WriteLine("Önplan threadinden merhaba"+state);
Thread’lerin Yönetimi Bir metodu arkaplan threadi olarak çalıştırmak her zaman yeterli olmayabilir. Threadleri manual olarak başlatmak, durdurmak, yeniden başlatmak ve sonlandırmak gerekebilir. Threadler ile bu şekilde çalışmak ise kaynak çatışmalarına (resource conflicts) neden olabilir.
Başlatma / Durdurma Bir thread, Thread nesnesi oluşturulduktan sonra Thread.Start ile başlatılabilir. Sonlandırmak için ise Thread.Abort kullanılır. (Abort durumunda ThreadAbortException uyarısı alınır ve bunun yakalanması ve ardından finally bloğu ile tüm kaynakların serbest bırakılması gerekmektedir.)
class ThreadTest { static void Main( ) Thread t = new Thread (WriteY); t.Start(); for (int i = 0; i < 1000; i++) Console.Write ("x"); } static void WriteY( ) for (int i = 0; i < 1000; i++) Console.Write ("y");
class Program { static void Main(string[] args) Thread DoWorkThread = new Thread(new ThreadStart(DoWork)); DoWorkThread.Start(); Thread.Sleep(5000); DoWorkThread.Abort(); Console.WriteLine("Main threadi sonlanmakta"); Thread.Sleep(6000); } public static void DoWork() { Console.WriteLine("DoWork metodu başka bir threadin içinde çalışmaktadır"); try { Thread.Sleep(5000); } catch (ThreadAbortException ex) { Console.WriteLine("Thread iptal edilmiştir");} finally {Console.WriteLine("Kaynaklar serbest bırakılmakta"); } Console.WriteLine("DoWork sonlandırılıyor");
Bir thread nesnesi oluştrulduktan sonra bu nesnenin önceliği Thread Bir thread nesnesi oluştrulduktan sonra bu nesnenin önceliği Thread.Priority özelliği ThreadPriority numaralandırıcısı kullanılarak düzenlenebilir. Thread önceliği, işletim sisteminin threadi nasıl zamanlayacağını (schedule time) kontrol eder.
ThreadPriority 4 kategori olarak değer almaktadır: Highest AboveNormal Normal Varsayılıdır. BelowNormal Lowest
Durumlar (Thread State) Thread’in durumu Thread.ThreadState özelliği yardımıyla öğrenilebilir. Threadler aşağıdaki durumlardan herhangi biri veya birkaçında olabilirler. - UnStarted - AbortRequested - Running - Aborted - Stopped - WaitSleepJoin - SuspendRequested - Suspended
Kaynaklara Erişimin Senkronize Edilmesi Eğer bir uygulama herhangi bir dosyaya yazma işlemi yapacaksa, dosyayı kilitler. Bu işlem, diğer uygulamaların bu dosyaya erişmesinin önüne geçer. Diğer uygulama dosyaya erişmek isterse ya kilidin açılmasını bekleyecek ya da dosyaya erişim istemini iptal edecektir.
Paylaşımlı kaynaklar üzerinde çalışan çok threadli uygulamalarda da benzer durum söz konusudur. Bu problemlerin giderilmesi için .NET sınıf kütüphanesi senkronizasyon nesneleri oluşturmuştur. Bu nesneler yardımıyla kaynaklar, threadler arasında eş zamanlı olarak koordine edilebilir.
Senkronizasyona gereksinim duyan kaynaklar şu şekilde olabilir: Sistem kaynakları(örn:iletişim portları) Çoklu processler tarafından paylaşılan kaynaklar(file handles) Çoklu threadler tarafından erişilen nesneler.
Monitor Monitor sınıfı kullanılarak kodun belirli bir kısmı kilitlenebilir. Kilit açılıncaya kadar diğer threadler bu kısma erişemezler. Bu sınıfın Monitor.Enter() ve Monitor.Exit() metotları kullanılabileceği gibi “lock” anahtar sözcüğü de kullanılabilir.
Reader/Writer Bazı durumlarda kod bloğu üzerinde bir thread değişiklik yaparken başka bir thread in okuma yapmasına izin verilebilir.
Interlocked Temel aritmatiksel işlemleri Thread güvenli olarak yapabilmek için “Interlocked” sınıfı kullanılır. Bu sınıf, atomik işlemleri aşağıdaki metotları çağırarak gerçekleştirir. Increment - CompareExchange Decrement - Add Exchange -Read