Megosztott erőforrásokhoz való hozzáférés szinkronizálása többszálas környezetben a Visual C# .NET vagy a Visual C# 2005 segítségével

A cikk fordítása A cikk fordítása
Cikk azonosítója: 816161 - A cikkben érintett termékek listájának megtekintése.
Az összes kibontása | Az összes összecsukása

A lap tartalma

Összefoglaló

A Microsoft Visual C# .NET vagy a Microsoft Visual C# 2005 alkalmazások a többszálas végrehajtási mechanizmusnak köszönhetően egy időben több feladatot is végrehajthatnak. A többszálas végrehajtási modell ugyanabban az időben különböző szálakat indíthat különböző feladatok végrehajtására. A többszálas végrehajtás az alkalmazások teljesítményét és válaszképességét is javítja.

Mivel a különböző szálak ugyanabban az időpontban is megpróbálhatnak hozzáférni ugyanahhoz az erőforráshoz, szükséges lehet az egyes szálak szinkronizálása a program többi részével. Ez a cikk a többszálas programozással kapcsolatos néhány tipikus forgatókönyvet tárgyal, és ismerteti a megosztott erőforrásokhoz való hozzáférés különböző szálak közötti szinkronizálásának módját.

Modulbeli globális adatok védelme többszálas környezetben

A metódusokban deklarált nyilvános (publikus) mezőket az alkalmazás minden szála eléri. Az e mezőkhöz való hozzáférés szinkronizálására létrehozhat egy tulajdonságot (property) a mező helyett, és egy ReaderWriterLock objektummal vezérelheti annak elérését. Hajtsa végre a következő lépéseket:
  1. Indítsa el a Microsoft Visual Studio .NET vagy a Microsoft Visual Studio 2005 alkalmazást.
  2. Kattintson a File (Fájl) menü New (Új) pontjának Project (Projekt) parancsára.
  3. Kattintson a Project Types (Projekttípusok) szakasz Visual C# Projects (Visual C# projektek), majd a Templates (Sablonok) szakasz Console Application (Konzolalkalmazás) elemére.

    Megjegyzés: Visual Studio 2005 esetében kattintson a Project Types (Projekttípusok) szakasz Visual C# , majd a Templates (Sablonok) szakasz Console Application (Konzolalkalmazás) elemére.
  4. A Név mezőbe írja be a MultiThreadApplication karakterláncot, majd kattintson az OK gombra.
  5. A Class1.cs fájlban található kódot cserélje ki a következő kódra:

    Megjegyzés: Visual Studio 2005 esetén az alapértelmezett fájl a következő: Program.cs.
    using System;
    using System.Threading;
    
    namespace MultiThreadApplication
    {
    	class Class1
    	{
    		private ReaderWriterLock rwl = new ReaderWriterLock();
    		private long myNumber;
    		public long Number   // A szám tulajdonság
    		{
    			get
    			{
    				//Olvasási zár elhelyezése az erőforrásra.
    				rwl.AcquireReaderLock(Timeout.Infinite);                
    				try
    				{
    					Console.WriteLine("A(z) {0}. szál megpróbálja lekérdezni Szám értékét.", Thread.CurrentThread.GetHashCode());
    					Thread.Sleep(50);
    					Console.WriteLine("A(z) {0}. szál lekérdezte a Szám értékét.", Thread.CurrentThread.GetHashCode());
    
    				}
    				finally
    				{
    					//A zár feloldása.
    					rwl.ReleaseReaderLock();
    				}
    				return myNumber;
    			}
    			set
    			{
    				//Írási zár elhelyezése az erőforrásra.
    				rwl.AcquireWriterLock(Timeout.Infinite);
    				try
    				{
    					Console.WriteLine("A(z) {0}. szál hozzákezd a Szám írásához", Thread.CurrentThread.GetHashCode());
    					Thread.Sleep(50);
    					myNumber = value;
    					Console.WriteLine("A(z) {0}. szál sikeresen írta a Szám értékét", Thread.CurrentThread.GetHashCode());
    				}
    				finally
    				{
    					//A zár feloldása.
    					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 szál létrehozása.
    			for( threadNum = 0; threadNum < 20; threadNum++)
    			{
    				threadArray[threadNum] = new Thread(myThreadStart);
    			}
    
    			//A szálak indítása.
    			for( threadNum = 0; threadNum < 20; threadNum++)
    			{   
    				threadArray[threadNum].Start();
    			}
    
    			//Várakozás, míg minden szál ki nem lép.
    			for( threadNum = 0; threadNum < 20; threadNum++)
    				threadArray[threadNum].Join();
    
    			Console.WriteLine("Minden művelet befejeződött. A kilépéshez nyomja meg az ENTER billentyűt.");
    			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. A projekt összeállítását (build) követően futtassa az alkalmazást.

Osztályok szálbiztossá tétele

Előfordulhat, hogy ugyanabban az időben több szál próbál hozzáférni egy objektumhoz. Az objektumhoz való hozzáférésért versengő szálak közül egyesek az objektum egy érvénytelen állapotával találkozhatnak, ha egy másik szál ugyanabban az időben épp módosítja az erőforrást. Ha például egy szál egy objektum egyik mezőjét olvassa, miközben azt a mezőt egy másik szál módosítja, az elsőként említett szál a mezőt érvénytelen állapotban kaphatja meg. Az ilyen eseteket versenyhelyzetnek nevezik.

Az ilyen szituációk elkerülése érdekében zárolással meg kell óvni a kód kritikus részeit a versenyhelyzetektől. Egy zár, melyet a Visual C# nyelvben a lock utasítás (és kulcsszó) jelöl, lehetővé teszi, hogy egyetlen végrehajtási szál kizárólagos végrehajtási jogokat szerezzen egy objektumra. A következő példa lépései a zárakat szemléltetik:
  1. Nyissa meg a Visual Studio .NET vagy a Visual Studio 2005 alkalmazást.
  2. Kattintson a File (Fájl) menü New (Új) pontjának Project (Projekt) parancsára.
  3. Kattintson a Project Types (Projekttípusok) szakasz Visual C# Projects (Visual C# projektek), majd a Templates (Sablonok) szakasz Console Application (Konzolalkalmazás) elemére.

    Megjegyzés: Visual Studio 2005 esetében kattintson a Project Types (Projekttípusok) szakasz Visual C# , majd a Templates (Sablonok) szakasz Console Application (Konzolalkalmazás) elemére.
  4. A Név mezőbe írja be a MultiThreadLockApplication karakterláncot, majd kattintson az OK gombra.
  5. A Class1.cs fájlban található kódot cserélje ki a következő kódra:
    using System;
    using System.Threading;
    
    namespace MultiThreadLockApplication
    {
    	class Student
    	{
    		private static string myTeacherName = "Balázs";
    		private string myName = "Barbara";
    		private static object somePrivateStaticObject = new Object();
    
    		public static string TeacherName
    		{
    			get
    			{
    				string theName;
    
    				// A megosztott taghoz való hozzáférés szinkronizálása.
    				lock(somePrivateStaticObject)
    				{
    					Console.WriteLine("A(z) {0}. szál elkezdi az oktató nevének lekérdezését.",Thread.CurrentThread.GetHashCode());
    					theName = myTeacherName;
    
    					// 0,3 másodpercnyi várakozás.
    					Thread.Sleep(300);
    					Console.WriteLine("A(z) {0}.szál lekérdezte az oktató nevét, mely:{1}.", Thread.CurrentThread.GetHashCode(), theName);
    				}
    				return theName;
    			}
    
    			set
    			{
    				lock(somePrivateStaticObject)
    				{
    					Console.WriteLine("A(z) {0}. szál elkezdi az oktató nevének beállítását.", Thread.CurrentThread.GetHashCode());
    					myTeacherName = value;
    
    					// 0,3 másodpercnyi várakozás.
    					Thread.Sleep(300);
    					Console.WriteLine("A(z) {0}.szál beállította az oktató nevét, mely:{1}.", Thread.CurrentThread.GetHashCode(), value);
    				}
    			}
    		}
    
    		public string GetName()
    		{
    			string theName;
    			lock(this)
    			{
    				Console.WriteLine("A(z) {0}. szál elkezdi a hallgató nevének lekérdezését.", Thread.CurrentThread.GetHashCode());
    				theName = myName;
    
    				// 0,3 másodpercnyi várakozás.
    				Thread.Sleep(300);
    				Console.WriteLine("A(z) {0}.szál lekérdezte a hallgató nevét, mely:{1}.", Thread.CurrentThread.GetHashCode(), theName);
    				return theName;
    			}
    		}
    
    		public string SetName(string NewName)
    		{
    			string theOldName;
    			lock(this)
    			{
    				Console.WriteLine("A(z) {0}. szál elkezdi a hallgató nevének beállítását.", Thread.CurrentThread.GetHashCode());
    				theOldName = myName;
    				myName = NewName;
    
    				// 0,3 másodpercnyi várakozás.
    				Thread.Sleep(300);
    				Console.WriteLine("A(z) {0}.szál beállította a hallgató nevét, mely:{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 = "Tamás";
    							break;
    						case 1:
    							Student.TeacherName = "Miklós";
    							break;
    						case 2:
    							Student.TeacherName = "József";
    							break;
    					}
    				}
    				else
    				{
    					theName = Student.TeacherName;
    				}
    			}
    			else
    			{
    				if( (rnd.Next() %2) != 0)
    				{
    					switch (rnd.Next() %3 )
    					{
    						case 0:
    							AStudent.SetName("Emília");
    							break;
    						case 1:
    							AStudent.SetName("Kálmán");
    							break;
    						case 2:
    							AStudent.SetName("Zoltán");
    							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();
    
    			// 20 munkatétel összegyűjtése a ThreadPool száltárolóba.
    			for (threadNum = 0 ; threadNum <= WorkItemNum -1 ; threadNum++) 
    			{
    				ThreadPool.QueueUserWorkItem(new WaitCallback(AccessClassResource),AStudent);
    			}
    
    			Done.WaitOne();
    			Console.WriteLine("Minden művelet befejeződött. A kilépéshez nyomja meg az ENTER billentyűt.");
    			Console.ReadLine();
    		}
    	}
    }
  6. A projekt összeállítását (build) követően futtassa az alkalmazást.

Hivatkozások

A Microsoft Developer Network (MSDN) kapcsolódó webhelye:
Thread Pooling (Száltárolás)
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconthreadpooling.asp
ReaderWriterLock
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconreaderwriterlock.asp
ReaderWriterLock Class (A ReaderWriterLock osztály)
http://msdn2.microsoft.com/en-us/library/system.threading.readerwriterlock(vs.71).aspx

Tulajdonságok

Cikk azonosítója: 816161 - Utolsó ellenőrzés: 2007. június 1. - Verziószám: 2.3
A cikkben található információ a következő(k)re vonatkozik:
  • Microsoft Visual C# 2005
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
Kulcsszavak: 
kbhowtomaster kbthread kbthreadsync KB816161
A Microsoft tudásbázisban szolgáltatott információkat "az adott állapotban", bárminemű szavatosság vagy garancia nélkül biztosítjuk. A Microsoft kizár mindennemű, akár kifejezett, akár vélelmezett szavatosságot vagy garanciát, ideértve a forgalomképességre és az adott célra való alkalmasságra vonatkozó szavatosságot is. A Microsoft Corporation és annak beszállítói semmilyen körülmények között nem felelősek semminemű kárért, így a közvetlen, a közvetett, az üzleti haszon elmaradásából származó vagy speciális károkért, illetve a kár következményeként felmerülő költségek megtérítéséért, még abban az esetben sem, ha a Microsoft Corporationt vagy beszállítóit az ilyen károk bekövetkeztének lehetőségére figyelmeztették. Egyes államok joga nem teszi lehetővé bizonyos károkért a felelősség kizárását vagy korlátozását, ezért a fenti korlátozások az ön esetében esetleg nem alkalmazhatók.

Visszajelzés küldése

 

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