Comment synchroniser l'accès à une ressource partagée dans un environnement multithreading à l'aide de Visual C#

Traductions disponibles Traductions disponibles
Numéro d'article: 816161 - Voir les produits auxquels s'applique cet article
Agrandir tout | Réduire tout

Sommaire

Résumé

Vous pouvez effectuer plusieurs tâches dans les applications Microsoft Visual C# à la fois à l'aide de multithreading. Multithreading peut démarrer des threads différents pour effectuer différentes tâches en même temps. Multithreading améliore également les performances et la réactivité de vos applications.

Comme plusieurs threads peuvent accéder à une ressource en même temps, peut ne vouloir synchroniser threads individuels sur d'autres parties de votre programme. Cet article décrit quelques scénarios courants par programmation multithreading et explique comment synchroniser l'accès à une ressource partagée entre plusieurs threads.

Permet de protéger vos données dans des modules dans un environnement multithread principal

Les champs publics de méthodes sont accessibles à tous les threads dans votre application. Pour synchroniser l'accès aux champs publics, vous pouvez utilisez la propriété à la place du champ et utiliser un objet ReaderWriterLock pour contrôler l'accès. Pour ce faire, procédez comme suit :
  1. Démarrez Microsoft Visual Studio.
  2. Dans le menu Fichier , pointez sur Nouveau , puis cliquez sur projet .
  3. Cliquez sur projets Visual C# sous types de projets , puis cliquez sur application console sous modèles .

    note Dans Visual Studio 2005 ou dans Visual Studio 2008, cliquez sur Visual C# sous types de projet , puis cliquez sur application console sous modèles .
  4. Dans la zone de texte Nom , tapez MultiThreadApplication et puis cliquez sur OK .
  5. Remplacez le code existant par le code suivant dans Class1.cs.

    note Dans Visual Studio 2005 et Visual Studio 2008, le fichier par défaut est système Program.cs.
    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("All operations have completed. Press enter to exit");
    			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. Générez le projet et ensuite exécuter l'application.

Permet de créer votre classe thread-safe

Plusieurs threads peuvent tenter d'accéder à un objet en même temps. Lorsque plusieurs threads concurrence pour l'accès à un objet en même temps, des threads peuvent s'afficher un état non valide si un autre thread modifie la ressource en même temps. Par exemple, si un thread lit le champ de l'objet pendant un autre thread est modification du champ, le premier thread peut recevoir un état non valide du champ. Cette situation est appelée une condition de concurrence.

Pour éviter cette situation, vous pouvez aider à protéger les sections importantes de votre code de conditions de compétition en utilisant des verrous. Un verrou, représenté par le verrouillage de mot clé C# relevé, permet à un seul thread d'exécution pour obtenir les droits d'exécution exclusif sur un objet. Les étapes d'exemple suivantes illustrent les verrous :
  1. Ouvrez Visual Studio.
  2. Dans le menu Fichier , pointez sur Nouveau , puis cliquez sur projet .
  3. Cliquez sur projets Visual C# sous types de projets , puis cliquez sur application console sous modèles .

    note Dans Visual Studio 2005 ou dans Visual Studio 2008, cliquez sur Visual C# sous types de projet , puis cliquez sur application console sous modèles .
  4. Dans la zone de texte Nom , tapez MultiThreadLockApplication et puis cliquez sur OK .
  5. Remplacez le code existant par le code suivant dans système Class1.cs:
    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("All operations have completed. Press enter to exit");
    			Console.ReadLine();
    		}
    	}
    }
  6. Générez le projet et ensuite exécuter l'application.

Références

Pour plus d'informations, voir aux sites Web de MSDN (Microsoft Developer Network) aux adresses suivantes :
Thread regroupement
http://msdn2.microsoft.com/en-us/library/0ka9477y(vs.71).aspx
ReaderWriterLock
http://msdn2.microsoft.com/en-us/library/bz6sth95(vs.71).aspx
Classe ReaderWriterLock
http://msdn2.microsoft.com/en-us/library/system.threading.readerwriterlock(vs.71).aspx

Propriétés

Numéro d'article: 816161 - Dernière mise à jour: lundi 14 juillet 2008 - Version: 3.1
Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft Visual C# 2008 Express Edition
  • Microsoft Visual C# 2005 Express Edition
  • Microsoft Visual C# .NET 2003 Initiation
  • Microsoft Visual C# .NET 2002 Initiation
Mots-clés : 
kbmt kbthreadsync kbthread kbhowtomaster KB816161 KbMtfr
Traduction automatique
IMPORTANT : Cet article est issu du système de traduction automatique mis au point par Microsoft (http://support.microsoft.com/gp/mtdetails). Un certain nombre d?articles obtenus par traduction automatique sont en effet mis à votre disposition en complément des articles traduits en langue française par des traducteurs professionnels. Cela vous permet d?avoir accès, dans votre propre langue, à l?ensemble des articles de la base de connaissances rédigés originellement en langue anglaise. Les articles traduits automatiquement ne sont pas toujours parfaits et peuvent comporter des erreurs de vocabulaire, de syntaxe ou de grammaire (probablement semblables aux erreurs que ferait une personne étrangère s?exprimant dans votre langue !). Néanmoins, mis à part ces imperfections, ces articles devraient suffire à vous orienter et à vous aider à résoudre votre problème. Microsoft s?efforce aussi continuellement de faire évoluer son système de traduction automatique.
La version anglaise de cet article est la suivante: 816161
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.

Envoyer des commentaires

 

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