ManualResetEvent vs. AutoResetEvent


Ambas as classes que são temas do post tem basicamente a mesma finalidade, ou seja, efetuar a sinalização entre threads. Isso permite que uma determinada thread notifique as outras threads que ela finalizou ou liberou um determinado recurso e, conseqüentemente, essas outras threads poderão dar seqüencia na execução.

Leve em consideração o seguinte código:

delegate void Executor();

private static XXX _resetEvent = new XXX(false);

static void Main(string[] args)
{
    new Executor(Teste1).BeginInvoke(null, null);
    new Executor(Teste2).BeginInvoke(null, null);
    new Executor(Teste3).BeginInvoke(null, null);

    Console.WriteLine(“Fim”);
    Console.ReadLine();
}

static void Teste1()
{
    Console.WriteLine(“Teste1 – Antes”);

    Thread.Sleep(5000); //Simula um processamento pesado
    _resetEvent.Set();
   
    Console.WriteLine(“Teste1 – Depois”);
}

static void Teste2()
{
    Console.WriteLine(“Teste2 – Antes”);
    _resetEvent.WaitOne();
    Console.WriteLine(“Teste2 – Depois”);
}

static void Teste3()
{
    Console.WriteLine(“Teste3 – Antes”);
    _resetEvent.WaitOne();
    Console.WriteLine(“Teste3 – Depois”);
}

Resultados para quando XXX = ManualResetEvent
Fim
Teste1 – Antes
Teste2 – Antes
Teste3 – Antes
Teste1 – Depois
Teste3 – Depois
Teste2 – Depois

Resultados para quando XXX = AutoResetEvent
Fim
Teste1 – Antes
Teste2 – Antes
Teste3 – Antes
Teste1 – Depois
Teste3 – Depois

Como sabemos, o método BeginInvoke fornecido pela instancia do delegate permite a chamado para o método que ele aponta de forma assíncrona, ou seja, será criada uma worker thread para cada um deles; sendo assim, os processos acontecerão paralelamente e o reset event está aqui para garantir a sincronização das informações, ou melhor, destes métodos.

Quando utilizamos o método WaitOne do ManualResetEvent nos métodos 2 e 3, eles aguardarão um sinal que, por sua vez, será dado através do método Set, também do ManualResetEvent. Enquanto isso não acontecer, os métodos 2 e 3 não darão sequencia no processamento. Se repararmos o resultado final, as mensagens (writelines) que a aparecem depois do método WaitOne retornará, isso quer dizer que ele ficará “travado” até receber o sinal para prosseguir. Uma vez recebido, todos aqueles que estiveremos pendentes serão executados.

Já com um AutoResetEvent, o processo é muito semelhante, com a exceção que quando o método Set for chamado, apenas uma thread da fila será executada. Isso explica o motivo pelo qual a mensagem do método 2 (“Teste2 – Depois“) não aparece no resultado final.

Bem, isso é uma das N possibilidades que o .NET fornece para efetuar a sincronização através de sinalização. Para aqueles que querem se aprofundar, vejam o namespace System.Threading.

Anúncios

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s