NASIL YAPILIR: Çok İş Parçacıklı Ortamda Visual C# .NET Kullanarak Bir Paylaşılan Kaynağa Erişimi Eşzamanlama

Makale çevirileri Makale çevirileri
Makale numarası: 816161 - Bu makalenin geçerli olduğu ürünleri görün.
Hepsini aç | Hepsini kapa

Bu Sayfada

™zet

Çoklu iş parçacıkları yardımıyla, Visual C# .NET uygulamalarında birden çok görevi aynı anda gerçekleştirebilirsiniz. Çok iş parçacığı kullanımı, farklı görevleri aynı anda tamamlayabilmeniz için farklı iş parçacıkları başlatabilir. Çok iş parçacığı, uygulamalarınızın performansını ve hızlı yanıt verme becerisini de artırır.

Birden çok iş parçacığı bir kaynağa aynı anda erişebildiği için, tek tek iş parçacıklarını programınızın diğer bölümleriyle eşzamanlı yapmak isteyebilirsiniz. Bu makalede, çok iş parçacıklı programlama ile ilgili bazı sık karşılaşılan senaryolar anlatılmakta ve bir paylaşılan kaynağa erişimin birden çok iş parçacığı arasında nasıl zamanlanacağı açıklanmaktadır.

Çok İş Parçacıklı Ortamda Global Verilerinizi Modüllerde Koruma

Yöntemlerdeki ortak alanlara uygulamanızdaki tüm iş parçacıkları tarafından erişilebilir. Ortak alanlara erişimi eşitlemek için, alan yerine özellik kullanabilir ve erişimi denetlemek amacıyla bir ReaderWriterLock nesnesi kullanabilirsiniz. Bunu yapmak için şu adımları izleyin:
  1. Visual Studio .NET'i başlatın.
  2. File (Dosya) menüsünde New'ın (Yeni) üzerine gelin ve Project'i (Proje) tıklatın.
  3. Project Types (Proje Türleri) altında Visual C# Projects'i (Visual C# Projeleri)ve sonra da Templates (Şablonlar) altında Console Application'ı (Konsol Uygulaması) tıklatın.
  4. Name (Ad) metin kutusuna ÇokİşParçacıklıUygulama yazın ve sonra OK'yi tıklatın.
  5. Class1.cs'de varolan kodun yerine aşağıdaki kodu yazın:
    using System;
    using System.Threading;
    
    namespace MultiThreadApplication
    {
    	class Class1
    	{
    		private ReaderWriterLock rwl = new ReaderWriterLock();
    		private long myNumber;
    		public long Number   // Number özelliği
    		{
    			get
    			{
    				//Kaynağı okumak için kilitle.
    				rwl.AcquireReaderLock(Timeout.Infinite);                
    				try
    				{
    					Console.WriteLine("İş Parçacığı:{0} Number değerini almaya başlıyor", Thread.CurrentThread.GetHashCode());
    					Thread.Sleep(50);
    					Console.WriteLine("İş Parçacığı:{0} Number değerini aldı", Thread.CurrentThread.GetHashCode());
    
    				}
    				finally
    				{
    					//Kilidi kaldır.
    					rwl.ReleaseReaderLock();
    				}
    				return myNumber;
    			}
    			set
    			{
    				//Kaynağı yazmak için kilitle.
    				rwl.AcquireWriterLock(Timeout.Infinite);
    				try
    				{
    					Console.WriteLine("İş Parçacığı:{0} Number değerine yazmaya başlıyor", Thread.CurrentThread.GetHashCode());
    					Thread.Sleep(50);
    					myNumber = value;
    					Console.WriteLine("İş Parçacığı:{0} Number değerine yazdı", Thread.CurrentThread.GetHashCode());
    				}
    				finally
    				{
    					//Kilidi kaldır.
    					rwl.ReleaseWriterLock();
    				}
    			}
    		}
    		
    		[STAThread]
    		static void Main(string[] args)
    		{
    			Thread []threadArray = new Thread[20]; 
    			int threadNum;
    
    
    			Class1 Myclass = new Class1();
    			ThreadStart myThreadStart = new ThreadStart(Myclass.AccessGlobalResource);
    
    			//20 tane iş parçacığı oluştur.
    			for( threadNum = 0; threadNum < 20; threadNum++)
    			{
    				threadArray[threadNum] = new Thread(myThreadStart);
    			}
    
    			//İş parçacıklarını başlat.
    			for( threadNum = 0; threadNum < 20; threadNum++)
    			{   
    				threadArray[threadNum].Start();
    			}
    
    			//İş parçacığı oluşturmanın bitmesini bekle.
    			for( threadNum = 0; threadNum < 20; threadNum++)
    				threadArray[threadNum].Join();
    
    			Console.WriteLine("Tüm işlemler tamamlandı. Çıkmak için Enter tuşuna basın");
    			Console.ReadLine();
    		}
    
    		public void AccessGlobalResource()
    		{
    			Random rnd = new Random();
    			long theNumber;
    			
    			if (rnd.Next() % 2 != 0)
    				theNumber = Number;
    			else
    			{
    				theNumber = rnd.Next();
    				Number = theNumber;
    			}
    
    		}
    	}
    }
    
  6. Projeyi derleyin ve uygulamayı çalıştırın.

Sınıfınızda İş Parçacıklarını Sorunsuz Kullanma

Birden çok iş parçacığı bir nesneye aynı anda erişmeye çalışabilir. Bir nesneye aynı anda birden çok iş parçacığı erişmeye çalıştığında, başka bir iş parçacığı kaynağı o sırada değiştiriyorsa bazı iş parçacıkları bir geçersiz durum bildirimi alabilir. Örneğin, bir iş parçacığı bir nesne alanını okurken başka bir iş parçacığı o alanı değiştiriyorsa, ilk iş parçacığı alanla ilgili bir geçersiz durum bildirimi alabilir. Buna yarış durumu adı verilir.

Bu durumdan kaçınmak için, kilitler kullanarak kodunuzdaki önemli bölümlerin yarış durumundan korunmasın sağlayabilirsiniz. Visual C# anahtar sözcüğü olan lock deyimi ile temsil edilen kilit, tek bir yürütme iş parçacığının bir nesnede özel yürütme hakları elde etsine olanak sağlar. Aşağıdaki örnekte kilitler adım adım gösterilmektedir:
  1. Visual Studio .NET'i açın.
  2. File (Dosya) menüsünde, New'ın (Yeni) üzerine gelin ve Project'i (Proje) tıklatın.
  3. Project Types (Proje Türleri) altında Visual C# Projects'i (Visual C# Projeleri) ve sonra da Templates (Şablonlar) altında Console Application'ı (Konsol Uygulaması) tıklatın.
  4. Name (Ad) metin kutusuna ÇokluİşParçacığıKilitlemeUygulaması yazın ve OK'yi tıklatın.
  5. Class1.cs'de varolan kodun yerine aşağıdaki kodu yazın:
    using System;
    using System.Threading;
    
    namespace MultiThreadLockApplication
    {
    	class Student
    	{
    		private static string myTeacherName = "Atacan";
    		private string myName = "Gamze";
    		private static object somePrivateStaticObject = new Object();
    
    		public static string TeacherName
    		{
    			get
    			{
    				string theName;
    
    				// Paylaşılan sayıya erişimi eşzamanlı yap.
    				lock(somePrivateStaticObject)
    				{
    					Console.WriteLine("İş Parçacığı {0} öğretmenin adını almaya başlıyor.",Thread.CurrentThread.GetHashCode());
    					theName = myTeacherName;
    
    					// 0,3 saniye bekle.
    					Thread.Sleep(300);
    					Console.WriteLine("İş Parçacığı {0} öğretmenin adını almayı tamamladı: {1}.", Thread.CurrentThread.GetHashCode(), theName);
    				}
    				return theName;
    			}
    
    			set
    			{
    				lock(somePrivateStaticObject)
    				{
    					Console.WriteLine("İş Parçacığı {0} öğretmenin adını ayarlamaya başlıyor.", Thread.CurrentThread.GetHashCode());
    					myTeacherName = value;
    
    					// 0,3 saniye bekle.
    					Thread.Sleep(300);
    					Console.WriteLine("İş Parçacığı {0} öğretmenin adını ayarlamayı tamamladı: {1}.", Thread.CurrentThread.GetHashCode(), value);
    				}
    			}
    		}
    
    		public string GetName()
    		{
    			string theName;
    			lock(this)
    			{
    				Console.WriteLine("İş Parçacığı {0} öğrencinin adını almaya başlıyor.", Thread.CurrentThread.GetHashCode());
    				theName = myName;
    
    				// 0,3 saniye bekle.
    				Thread.Sleep(300);
    				Console.WriteLine("İş Parçacığı {0} öğrencinin adını almayı tamamladı: {1}", Thread.CurrentThread.GetHashCode(), theName);
    				return theName;
    			}
    		}
    
    		public string SetName(string NewName)
    		{
    			string theOldName;
    			lock(this)
    			{
    				Console.WriteLine("İş Parçacığı {0} öğrencinin adını ayarlamaya başlıyor.", Thread.CurrentThread.GetHashCode());
    				theOldName = myName;
    				myName = NewName;
    
    				// 0,3 saniye bekle.
    				Thread.Sleep(300);
    				Console.WriteLine("İş Parçacığı {0} öğrencinin adını ayarlamayı tamamladı: {1}", Thread.CurrentThread.GetHashCode(), NewName);
    			}
    			return theOldName;
    		}
    	}
    
    	class Class1
    	{
    		public static int WorkItemNum = 20;
    		public static AutoResetEvent Done = new AutoResetEvent(false);
    
    		public static void AccessClassResource(object state)
    		{
    			Random rnd = new Random();
    			string theName;
    			Student AStudent = (Student) state;
    
    			if( (rnd.Next() %2) != 0)
    			{
    				if( (rnd.Next() %2) != 0)
    				{
    					switch (rnd.Next() %3 )
    					{
    						case 0:
    							Student.TeacherName = "Tan";
    							break;
    						case 1:
    							Student.TeacherName = "Emre";
    							break;
    						case 2:
    							Student.TeacherName = "Kemal";
    							break;
    					}
    				}
    				else
    				{
    					theName = Student.TeacherName;
    				}
    			}
    			else
    			{
    				if( (rnd.Next() %2) != 0)
    				{
    					switch (rnd.Next() %3 )
    					{
    						case 0:
    							AStudent.SetName("Jale");
    							break;
    						case 1:
    							AStudent.SetName("Filiz");
    							break;
    						case 2:
    							AStudent.SetName("Oya");
    							break;
    					}
    				}
    				else
    				{
    					theName = AStudent.GetName();
    				}
    			}
    
    			if(Interlocked.Decrement( ref WorkItemNum) == 0)
    			{
    				Done.Set();
    			}
    		}
    
    		[STAThread]
    		static void Main(string[] args)
    		{
    			int threadNum;
    			Student AStudent = new Student();
    
    			// ThreadPool'da 20 tane çalışma öğesini sıraya al.
    			for (threadNum = 0 ; threadNum <= WorkItemNum -1 ; threadNum++) 
    			{
    				ThreadPool.QueueUserWorkItem(new WaitCallback(AccessClassResource),AStudent);
    			}
    
    			Done.WaitOne();
    			Console.WriteLine("Tüm işlemler tamamlandı. Çıkmak için Enter tuşuna basın");
    			Console.ReadLine();
    		}
    	}
    }
    
  6. Projeyi derleyin ve uygulamayı çalıştırın.

Referanslar

Daha fazla bilgi için, aşağıdaki Microsoft Developer Network (MSDN) Web sitelerine bakın:
İş Parçacığı Havuzu
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconthreadpooling.asp
ReaderWriterLock
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconreaderwriterlock.asp
ReaderWriterLock Sınıfı
http://msdn2.microsoft.com/en-us/library/system.threading.readerwriterlock(vs.71).aspx

Özellikler

Makale numarası: 816161 - Last Review: 1 Haziran 2007 Cuma - Gözden geçirme: 2.2
Bu makaledeki bilginin uygulandığı durum:
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
Anahtar Kelimeler: 
kbthreadsync kbthread kbhowtomaster KB816161

Geri Bildirim Ver

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com