Postupy: Synchonizace přístupu ke sdílenému prostředku v prostředí s více podprocesy pomocí aplikace Visual C# .NET

Překlady článku Překlady článku
ID článku: 816161 - Produkty, které se vztahují k tomuto článku.
Rozbalit všechny záložky | Minimalizovat všechny záložky

Na této stránce

Souhrn

V aplikacích Visual C# .NET můžete současně provádět několik úkolů pomocí podprocesů. Při souběžném spuštění různých podprocesů můžete najednou dokončit více rozdílných úkolů. Podprocesy také zvyšují výkon a reakce aplikací.

Více podprocesů může používat současně stejný prostředek. Proto je vhodné synchronizovat jednotlivé podprocesy s ostatními částmi programu. Tento článek popisuje některé běžné scénáře programování s využitím podprocesů a vysvětluje způsob synchronizace přístupu několika podprocesů ke sdílenému prostředku.

Nápověda k ochraně globálních údajů v modulech v prostředí s více podprocesy

Veřejná pole metod jsou přístupná všem podprocesům v aplikaci. Pokud chcete synchronizovat přístup k veřejným polím, můžete použít vlastnost místo pole a řídit přístup pomocí objektu ReaderWriterLock. Použijte tento postup:
  1. Spusťte aplikaci Visual Studio .NET.
  2. V nabídce File (Soubor) přejděte na příkaz New (Nový) a klepněte na příkaz Project (Projekt).
  3. V části Project Types (Typy projektů) klepněte na odkaz Visual C# Projects (Projekty aplikace Visual C#) a potom klepněte v části Templates (Šablony) na odkaz Console Application (Aplikace konzoly).
  4. V textovém poli Name (Název) zadejte název MultiThreadApplication a klepněte na tlačítko OK.
  5. Nahraďte existující kód v modulu Class1.cs následujícím kódem:
    using System; using System.Threading;
    
    namespace MultiThreadApplication { class Class1 { private ReaderWriterLock rwl = new ReaderWriterLock(); private long myNumber; public long Number   // the Number property { get { //Acquire a read lock on the resource. rwl.AcquireReaderLock(Timeout.Infinite); try { Console.WriteLine("Thread:{0} starts getting the Number", Thread.CurrentThread.GetHashCode()); Thread.Sleep(50); Console.WriteLine("Thread:{0} got the Number", Thread.CurrentThread.GetHashCode());
    
    				} finally { //Release the lock. rwl.ReleaseReaderLock(); } return myNumber; } set { //Acquire a write lock on the resource. rwl.AcquireWriterLock(Timeout.Infinite); try { Console.WriteLine("Thread: {0} start writing the Number", Thread.CurrentThread.GetHashCode()); Thread.Sleep(50); myNumber = value; Console.WriteLine("Thread: {0} written the Number", Thread.CurrentThread.GetHashCode()); } finally { //Release the lock. 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);
    
    			//Create 20 threads. for( threadNum = 0; threadNum < 20; threadNum++) { threadArray[threadNum] = new Thread(myThreadStart); }
    
    			//Start the threads. for( threadNum = 0; threadNum < 20; threadNum++) { threadArray[threadNum].Start(); }
    
    			//Wait until all the thread spawn out finish. for( threadNum = 0; threadNum < 20; threadNum++) threadArray[threadNum].Join();
    
    			Console.WriteLine("Všechny operace byly dokončeny. Stisknutím klávesy ENTER ukončíte tento program."); 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. Vytvořte projekt a spusťte aplikaci.

Nápověda k zabezpečení třídy v podprocesu

Více podprocesů se může pokusit o současný přístup k objektu. Jestliže se ve stejnou chvíli pokusí o přístup k objektu více podprocesů, mohou některé z nich obdržet informaci o neplatném stavu (v případě souběžných úprav prostředku jiným podprocesem). Pokud například jeden podproces čte pole objektu, zatímco jej jiný podproces upravuje, může první podproces obdržet neplatný stav pole. Tato situace je označována jako spor.

Chcete-li se této situaci vyhnout, můžete kritické části kódu ochránit před vznikem sporu pomocí zámků. Zámek, který je představován příkazem zámku aplikace Visual C#, umožňuje získání výhradních práv pro přístup k objektu pouze jedinému podprocesu. Kroky uvedené v následujícím příkladu představují použití zámků:
  1. Spusťte aplikaci Visual Studio .NET.
  2. V nabídce File (Soubor) přejděte na příkaz New (Nový) a klepněte na příkaz Project (Projekt).
  3. V části Project Types (Typy projektů) klepněte na odkaz Visual C# Projects (Projekty aplikace Visual C#) a v části Templates (Šablony) klepněte na odkaz Console Application (Aplikace konzoly).
  4. Do textového pole Name (Název) zadejte název MultiThreadLockApplication a klepněte na tlačítko OK.
  5. Nahraďte existující kód v modulu Class1.cs následujícím kódem:
    using System; using System.Threading;
    
    namespace MultiThreadLockApplication { class Student { private static string myTeacherName = "Bill"; private string myName = "Grace"; private static object somePrivateStaticObject = new Object();
    
    		public static string TeacherName { get { string theName;
    
    				// Synchronize access to the shared member. lock(somePrivateStaticObject) { Console.WriteLine("Thread {0} starts to get the teacher's name",Thread.CurrentThread.GetHashCode()); theName = myTeacherName;
    
    					// Wait for 0.3 second. Thread.Sleep(300); Console.WriteLine("Thread {0} finished to get the teacher's name:{1}.", Thread.CurrentThread.GetHashCode(), theName); } return theName; }
    
    			set { lock(somePrivateStaticObject) { Console.WriteLine("Thread {0} starts to set the teacher's name.", Thread.CurrentThread.GetHashCode()); myTeacherName = value;
    
    					// Wait for 0.3 second. Thread.Sleep(300); Console.WriteLine("Thread {0} finished to set the teacher's name:{1}.", Thread.CurrentThread.GetHashCode(), value); } } }
    
    		public string GetName() { string theName; lock(this) { Console.WriteLine("Thread {0} starts to get the student's name.", Thread.CurrentThread.GetHashCode()); theName = myName;
    
    				// Wait for 0.3 second. Thread.Sleep(300); Console.WriteLine("Thread {0} finished to get the student's name:{1}", Thread.CurrentThread.GetHashCode(), theName); return theName; } }
    
    		public string SetName(string NewName) { string theOldName; lock(this) { Console.WriteLine("Thread {0} starts to set the student's name.", Thread.CurrentThread.GetHashCode()); theOldName = myName; myName = NewName;
    
    				// Wait for 0.3 second. Thread.Sleep(300); Console.WriteLine("Thread {0} finished to set the student's name:{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 = "Tom"; break; case 1: Student.TeacherName = "Mike"; break; case 2: Student.TeacherName = "John"; break; } } else { theName = Student.TeacherName; } } else { if( (rnd.Next() %2) != 0) { switch (rnd.Next() %3 ) { case 0: AStudent.SetName("Janet"); break; case 1: AStudent.SetName("David"); break; case 2: AStudent.SetName("Ben"); 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();
    
    			// Queue up 20 work items in the ThreadPool. for (threadNum = 0 ; threadNum <= WorkItemNum -1 ; threadNum++) { ThreadPool.QueueUserWorkItem(new WaitCallback(AccessClassResource),AStudent); }
    
    			Done.WaitOne(); Console.WriteLine("Všechny operace byly dokončeny. Stisknutím klávesy ENTER ukončíte tento program."); Console.ReadLine(); } } }
  6. Vytvořte projekt a spusťte aplikaci.

Odkazy

Další informace naleznete na následujících webech služby MSDN (Microsoft Developer Network):
Thread Pooling (Fond podprocesů)
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 (Třída ReaderWriterLock)
http://msdn2.microsoft.com/en-us/library/system.threading.readerwriterlock(vs.71).aspx

Vlastnosti

ID článku: 816161 - Poslední aktualizace: 1. června 2007 - Revize: 1.2
Informace v tomto článku jsou určeny pro produkt:
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
Klíčová slova: 
kbthreadsync kbthread kbhowtomaster KB816161

Dejte nám zpětnou vazbu

 

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