Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

RSS iMasters

[Resolvido] Sincronização de Threads em C#

Recommended Posts

Um aviso aos leitores deste artigo: boa parte doconteúdo é uma tradução do artigo ?Thread Synchronization (C# andVisual Basic)? disponibilizado pela Microsoft. Aproveite a leitura!

 

Um dos benefícios do uso de múltiplas threads em uma aplicação é que cadauma delas éexecutada de forma assíncrona. Em aplicações desktop, istopermite que tarefasque consomem muito tempo possam ser executada em segundo plano enquanto a janela do aplicativo e oscontroles continuamrespondendo. 

 

 

Para aplicações em servidores, múltiplastarefas fornecem a capacidade de lidar comcada solicitação de entrada com uma thread diferente, caso contrário, cada novo pedido não seráatendido até que o pedido anteriortenha completado.

 

No entanto, a natureza assíncrona de threads significa que o acesso a recursos compartilhados, como arquivos, conexões de rede e memória devem ser sincronizados. Caso contrário, duas ou mais threads podem acessar o mesmo recurso ao mesmo tempo, e cada um desconhece a atuação da outra ação. Oresultado é a corrupção de dados imprevisível e possíveis deadlocks.

 

Há algum tempo, fiz outros artigos que demonstram o uso dethreads em C# e Visual Basic. Você pode encontrá-los aqui:

 

Lock e SyncLock

O Lock (C#) e o SyncLock (VB.NET) sãodeclarações que podem ser utilizadas para garantir que um bloco de código sejaexecutado até sua conclusão, prevenindo a interrupção da execução por outrasthreads.

 

Essas declarações são interpretadas pelo compilador como bloqueiospara um determinado objeto em um bloco de códigos. Se outra thread tentaexecutar o código envolvido pelo lock/SyncLock, ela evai esperar até que aprimeira thread termine a execução e libere o objeto/código bloqueado.

 

//C#

public class LockTest

{

public void TestarLock()

{

lock (this)

{

// Código que estará protegido pelo lock.

}

}

}

Sincronização de eventos e Wait Handles

Existem dois tipos de sincronização: AutoResetEvent eManualResetEvent. Eles diferem apenas na medida em que as mudanças são setadasautomaticamento no AutoResetEvent e manualmente no ManualResetEvent. OManualResetEvent permite que qualquer número de threads possa ser alinhado eter seu estado atualizado.

 

Métodos são usados para esperar a execução de um ou maisthreads. Esses métodos indicam ao compilador quando e quantas threads devem tero processamento concluído para que o fluxo continue. São eles: WaitOne, WaitAnye WaitAll.

 

WaitOne faz com que o compilador espere a execução de um únicothread estar concluída. WaitAny faz o compilador aguardar a execução dosmétodos indicados. WaitAll bloqueia a execução até que todas as threads estejamconcluídas. Para sinalizar a conclusão da execução de uma thread, usa-se ométodo Set.

 

// C#

namespace GerenciaSincronizacao

{

public class GerenciarThreads

{

private ManualResetEvent[] manualResetEvent;

 

private void ExecutarThread0(object obj)

{

Thread.Sleep(20000);

Console.WriteLine("Thread 0 concluída!");

manualResetEvent[0].Set();

}

 

private void ExecutarThread1(object obj)

{

Thread.Sleep(13000);

Console.WriteLine("Thread 1 concluída!");

manualResetEvent[1].Set();

}

 

private void ExecutarThread2(object obj)

{

Thread.Sleep(9000);

Console.WriteLine("Thread 2 concluída!");

manualResetEvent[2].Set();

}

 

private void ExecutarThread3(object obj)

{

Thread.Sleep(17000);

Console.WriteLine("Thread 3 concluída!");

manualResetEvent[3].Set();

}

 

public void Executar()

{

manualResetEvent = new ManualResetEvent[4];

 

manualResetEvent[0] = new ManualResetEvent(false);

ThreadPool.QueueUserWorkItem(this.ExecutarThread0);

 

manualResetEvent[1] = new ManualResetEvent(false);

ThreadPool.QueueUserWorkItem(this.ExecutarThread1);

 

manualResetEvent[2] = new ManualResetEvent(false);

ThreadPool.QueueUserWorkItem(this.ExecutarThread2);

 

manualResetEvent[3] = new ManualResetEvent(false);

ThreadPool.QueueUserWorkItem(this.ExecutarThread3);

 

WaitHandle.WaitAll(manualResetEvent);

}

}

 

class Program

{

static void Main(string[] args)

{

GerenciarThreads gt = new GerenciarThreads();

gt.Executar();

 

Console.WriteLine("Pressione ENTER para terminar.");

Console.ReadKey();

}

}

}

A classeInterlocked

Você pode usar os métodos da classe Interlocked para evitarproblemas que podem ocorrer quando várias threads tentam simultaneamenteatualizar ou comparar um mesmo valor. Os métodos dessa classe permitem que vocêassegure o incremento, decremento, troca e comparação entre valores em qualquerthread.

 

As operações mais utilizadas desta classe são:

 

  • O método Add adiciona um valor inteiro parauma variável e retorna o novo valor da variável.

  • O método Read lê um valor inteiro de 64 bits.

  • Os métodos Increment e Decrement sãoutilizados para incrementar ou decrementar valores em uma variável e retornam ovalor resultante.

Ocódigo a seguir demonstra o uso do Increment:

 

// C#

private static ManualResetEvent[] manualResetEvents;

 

public void Teste()

{

int intQuantidadeInteracoes = 10;

int intContador = 0;

 

manualResetEvents = new ManualResetEvent[intQuantidadeInteracoes];

 

for (int i = 0; i < intQuantidadeInteracoes; i++)

{

manualResetEvents[intContador] = new ManualResetEvent(false);

 

ThreadPool.QueueUserWorkItem(this.Executar, intContador);

 

Interlocked.Increment(ref intContador);

}

 

WaitHandle.WaitAll(manualResetEvents);

}

 

public void Executar(object intContador)

{

Console.WriteLine("Posição atual do contador: {0}",

Convert.ToInt32(intContador));

 

manualResetEvents[Convert.ToInt32(intContador)].Set();

}

Referências

 

http://imasters.com.br/artigo/20518/c-sharp/sincronizacao-de-threads-em-c

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.