Como sincronizar o acesso a um recurso compartilhado em um ambiente multithread usando translation from VPE for Csharp Visual

Traduções deste artigo Traduções deste artigo
ID do artigo: 816161 - Exibir os produtos aos quais esse artigo se aplica.
Expandir tudo | Recolher tudo

Neste artigo

Sumário

Você pode executar várias tarefas em aplicativos de Microsoft Visual translation from VPE for Csharp ao mesmo tempo usando multithreading. Multithreading pode iniciar threads diferentes para concluir tarefas diferentes ao mesmo tempo. Multithreading também melhora o desempenho e capacidade de resposta dos seus aplicativos.

Como vários segmentos podem acessar um recurso ao mesmo tempo, talvez queira sincronizar segmentos individuais com outras partes do seu programa. Este artigo descreve alguns cenários comuns com a programação multithread e explica como sincronizar o acesso a um recurso compartilhado entre vários threads.

Ajudar a proteger seus dados globais em módulos em um ambiente multithread

Os campos públicos em métodos estão acessíveis a todos os threads em seu aplicativo. Para sincronizar o acesso a campos públicos, você pode usar a propriedade em vez de campo e usar um objeto ReaderWriterLock para controlar o acesso. Para fazer isso, execute as seguintes etapas:
  1. Inicie o Microsoft Visual Studio.
  2. No menu arquivo , aponte para novo e, em seguida, clique em Project .
  3. Clique em projetos do Visual translation from VPE for Csharp em Project Types e clique em Aplicativo de console em modelos .

    Observação No Visual Studio 2005 ou no Visual Studio 2008, clique em translation from VPE for Csharp Visual em Tipos de projeto e, em seguida, clique em Aplicativo de console em modelos .
  4. Na caixa de texto nome , digite MultiThreadApplication e, em seguida, clique em OK .
  5. Substitua o código existente com o seguinte código no Class1.cs.

    Observação No Visual Studio 2005 e no Visual Studio 2008, o arquivo padrão é sistema 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. Criar o projeto e, em seguida, executar o aplicativo.

Ajudar a tornar sua classe thread-safe

Vários segmentos podem tentar acessar um objeto ao mesmo tempo. Quando mais de um segmento concorre para acessar um objeto ao mesmo tempo, alguns threads podem receber um estado inválido se outro thread modificar o recurso ao mesmo tempo. Por exemplo, se um thread lê o campo do objeto enquanto outro thread está modificando o campo, o primeiro thread poderá receber um estado inválido do campo. Essa situação é chamada de uma condição de corrida.

Para evitar essa situação, você pode ajudar a proteger as seções críticas do seu código de condições de corrida usando bloqueios. Um bloqueio, representado pelo bloqueio de palavra-chave translation from VPE for Csharp Visual Statement, permite que um único segmento de execução para obter direitos de execução exclusivo em um objeto. As etapas de exemplo a seguir demonstram bloqueios:
  1. Abra o Visual Studio.
  2. No menu arquivo , aponte para novo e, em seguida, clique em Project .
  3. Clique em projetos do Visual translation from VPE for Csharp em Project Types e clique em Aplicativo de console em modelos .

    Observação No Visual Studio 2005 ou no Visual Studio 2008, clique em translation from VPE for Csharp Visual em Tipos de projeto e, em seguida, clique em Aplicativo de console em modelos .
  4. Na caixa de texto nome , digite MultiThreadLockApplication e, em seguida, clique em OK .
  5. Substitua o código existente com o seguinte código no sistema 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. Criar o projeto e, em seguida, executar o aplicativo.

Referências

Para obter mais informações, consulte os seguintes sites da Microsoft Developer Network (MSDN):
Thread pool
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

Propriedades

ID do artigo: 816161 - Última revisão: segunda-feira, 14 de julho de 2008 - Revisão: 3.1
A informação contida neste artigo aplica-se a:
  • Microsoft Visual C# 2008 Express Edition
  • Microsoft Visual C# 2005 Express Edition
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
Palavras-chave: 
kbmt kbthreadsync kbthread kbhowtomaster KB816161 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 816161

Submeter comentários

 

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