Threading
Threading konusu, yazılım geliştirme sürecinde çok önemli bir kavramdır. Thread’ler sayesinde birçok işi aynı anda eş zamanlı olarak yapmak mümkündür. Yürütülen iş parçacıklarını bir süre bekletmek veya istenen anda sonlandırmakta mümkündür.
Threading işlemlerini yöneten tipler, .Net Framework tarafında System.Threading alanında barınmaktadır.
Threading konusuna başlamadan önce Thread sınıfını tanımak gerekmektedir. Bu sınıf tek bir iş parçacığı nesnesidir. Yani bir iş parçacığını başlatmayı ve süreci yönetmeyi sağlar.
Bir iş parçacığının oluşturulması şu şekilde olmaktadır.
class SingleThreading { public void StartSingleOperation() { Thread thread = new Thread(new ThreadStart(work1)); thread.Start(); } private void work1() { Console.WriteLine("This is worker thread. ThreadID: {0}", Thread.CurrentThread.ManagedThreadId); } }
Burada SingleThreading sınıfı içersinde work1 isimli işi yapan, thread nesnesidir. Yani StartSingleOperation metodu çalıştığında programdaki diğer yürütülen işlemlerin bitmesini beklemeden work1 isimli iş yapılmaya başlanır.
Multiple Thread Kullanımı
Bazı durumlarda birden fazla thread kullanarak iş süreçlerini yönetmek istediğimiz durumlar olabilir. Yani birbirini etkilemeyen, sıra beklemeden eş zamanlı olarak yapılması planlanan süreçleri için aşağıdaki örneği verebiliriz.
class MultipleThreading { public void StartMultipleWriter() { Thread th1 = new Thread(new ThreadStart(WriteX)); Thread th2 = new Thread(new ThreadStart(WriteO)); th1.Start(); th2.Start(); } private void WriteX() { for (int i = 0; i < 300; i++) { Console.Write("X"); } } private void WriteO() { for (int i = 0; i < 300; i++) { Console.Write("O"); } } }
Burada th1 ve th1 isimli iki nesne örneği birbirinden bağımsız olarak iki ayrı iş parçacığını yönetmektedir. Burada işlemci iş yoğunluğuna göre eşzamanlama işlemini gerçekleştirmektedir. Yani iki farklı iş bitene kadar biraz WriteX metodundan birazda WriteO metodundan yürütme işlemi yapmaktadır. Bunun ispatı olarak da şu ekran çıktısını verebiliriz.
Görüldüğü gibi bir süre X yazma işlemi yapılmış, bir süre de O yazma işlemi yapılmış. Program her çalıştığında X ve O farklı yerlerde olabilir. Çünkü işlemcinin durumuna göre hangi metodun ne kadar çalışacağı belirlenmektedir.
Önceliklerin belirlenmesi (Thread Priority)
Bazı durumlarda çoklu thread kullanırken öncelik vermek istenen iş parçacıkları olabilir. Birçok thread aynı anda start edildiğinde, bunlardan bir tanesi diğerlerine göre öncelikli olması gerekebilir. Bu gibi durumlarda imdadımıza yetişen Thread.Priority özelliğidir. Bu özellik bir enumerasyon tipindedir. Bu enum tipi, bünyesinde; Highest, AboveNormal, Normal, BelowNormal, Lovest gibi seçenekleri tutmaktadır.
Yukardaki örnekte iş parçacıkları başlatılmadan önce öncelikleri şu kelikde belirleyelim.
public void StartMultipleWriter() { Thread th1 = new Thread(new ThreadStart(WriteX)); Thread th2 = new Thread(new ThreadStart(WriteO)); th1.Priority = ThreadPriority.Lowest; th2.Priority = ThreadPriority.Highest; th1.Start(); th2.Start(); }
Yani WriteX metodu WriteO metodundan daha az öncelikli olsun. Bu durumda işlemci, WriteO metodunun işlemini daha önce bitirecektir.
Ekran çıktısından da anlaşılacağı gibi WriteX metodu daha az öncelikli olduğundan X yazma işlemi sonlara bırakılmıştır.
Thread.Join metodu ile iş parçacığının bitmesini beklemek
Thread.Join() metodu bir iş parçacığının başka bir göreve başlamadan önce tamamlanması için bekletir. Ayrıca metodun overload edilmiş bir hali ile, belirlenen bir süre kadar işlemin yapılması sağlanır. Belirlenen süre içinde işlem biterse metod geriye True değer döndürür, aksi halde False döndürür.
Örneğin “Thread1” ve “Thread2” adında iki iş parçacığını sırayla çalıştırdığımızı varsayalım. “Thread1” çalışırken ”Thread2.Join()” metodunu çağırdığımızda “Thread2” işlemini bitirene kadar “Thread1” bekler. Ardından “Thread1” işlemine devam eder. Eğer ”Thread2.Join(int)” metodu çağırıldğında ise, belirlenen süre içinde işlem bitmezsse bekleyen diğer iş parçacığı çalışmaya başlar.
Bu yazımızda threading işlemlerinden bahsetmiş olduk. Umarım faydalı bir yazı olmuştur.
merhabalar, threading ile ilgili bilginize danışmak istiyorum: bir datasettten tüm kayıtların iki threadli bir yapıda silinmesi işlemini yapıyorum. Birinci thread, 0 ile rows.count/2 kadarını diğer thread de rows.count/2 den rows.count arasındaki rowlari silecek. ancak yazdığım prg. bazen düzgün çalışıyor, bazen thread ile ilgili hata veriyor. sizce yapı nasıl kurgulanmalı.
benim yaptığım ise şöyle:
thread1.start()
thread2.start()
thread1.join()
thread2.join()
ilginize teşekkürler, iyi günler…
Muhtemelen bir indexleme hatası oluyor. Çünkü datatable içinde 100 kayıt varsa thread1 çalıştığında işlem bitince 50 adet kalacak, bu durumda 50’den 100’e kadar olan kayıtlar için örneğin 51 bulunamadı diyedek. Çünkü Count/2 yeniden hesaplanıyor olacak.
dataSet.Tables.Clear() tüm kayıtları zaten temizliyor hızlı bir şekilde.
dataSet.Tables.RemoveAt(index) ise istediğiniz indexi silmenize yardımcı oluyor.
Tabi bu işleme, yani thread kullanarak silmeye sizi sevkeden bir sebep vardır mutlaka.
Bence gerçekten thread kullanılmalı mı? diye sorgulamalısınız.
Makale oldukca guzel olmus, sdaece bir hatirlatma yapmak istedim. 1-Wait Fonksiyonları ile ilgili olarak, eger bir thread window create ediyorsa (ki bazi durumlarda bu window create etme işi e7ağrılan fonksiyon tarafından yapılıyor mesela CoInitialize fonksiyonu window create ediyor) Wait fonksiyonlarında MsgWaitForMultipleObjects i kullanmak gerekiyor. Aksi halde WairForSingle/MultipleObjects e7agrılırsa işletim sisteminin kararsız olmasına neden olunabilliyor.2- Bir mutex senkronizasyon nesnesi CreateMutex API’si ile oluşturulur ve CloseHandle API’si ile de işletim sisteminden silinir Cfcmlesinde de aslinda CloseHandle ile nesne işletim sisteminden kesin olarak silinmeyebilir, cunku handle lar ie7in işletim sisteminde reference couting mekanizması vardır. Her bir closehandle ie7in bu count bir azalir ve eger sifir olursa nesne işletim sisteminden silinir. Saygilar sunarim.,
merhaba
Join methodu konusunda sürekli farklı şeyler okuyorum. Ben birbirini beklemeden işini yapan birkaç thred oluşturmak ancak en son fonksiyondan return yapmadan önce hepsinin bittiğinden emin olmak istiyorum. Bu durumda nasıl bir yapı kullanmalıyım. Yaptıgım join yada isAlive kontrollerinde bir dogru bir yanlış çalışıyorlar.
Çok güzel açıklamışsınız.Teşekkür ederim.