Evento AutoReset em C#

Resumo : neste tutorial, você aprenderá como usar a AutoResetEventclasse C# para sincronizar threads e controlar suas execuções sinalizando eventos entre elas.

Introdução à classe C# AutoResetEvent

A AutoResetEventclasse permite que vários threads se comuniquem entre si sinalizando eventos.

An AutoResetEventtem dois estados:

  • Sinalizado
  • Não sinalizado

Quando um AutoResetEventobjeto é sinalizado, um único thread em espera será liberado e continuará sua execução.

No entanto, quando um AutoResetEventobjeto é Unsignaled, o thread em espera será bloqueado até que AutoResetEventseja sinalizado novamente.

O AutoResetEventobjeto possui dois métodos principais que controlam seu estado: Waitone()e Set():

  • O WaitOne()método bloqueia o thread atual até que AutoResetEventseja sinalizado ou um intervalo de tempo limite tenha decorrido.
  • O Set()método mudou o estado para AutoResetEventnão sinalizado e libera um único thread em espera.

Na prática, você usa o AutoResetEventem aplicativos multithread onde um thread precisa esperar que outro thread conclua seu trabalho antes de continuar.

Por exemplo, em um cenário produtor-consumidor, o encadeamento consumidor pode esperar que o encadeamento produtor produza os dados antes que o encadeamento consumidor possa consumir os dados.

Para usar a AutoResetEventclasse, você pode seguir estas etapas:

Primeiro, crie um AutoResetEventobjeto:

var autoResetEvent = new AutoResetEvent(false);Linguagem de código:  C#  ( cs )

O parâmetro false define o estado do AutoResetEventobjeto como Unsignaled.

Segundo, crie um thread que aguarde a sinalização do evento:

var t = new Thread(() =>
{
    // do some work
    // ...
    // wait for the event to be signaled
    autoResetEvent.WaitOne(); 
    
    // continue execution after the event is signaled
    // do something else
});Linguagem de código:  C#  ( cs )

Terceiro, inicia o tópico:

t.Start();Linguagem de código:  C#  ( cs )

Quarto, faça algumas operações antes que o thread possa continuar a executar e sinalizar AutoResetEventchamando o Set()método:

autoResetEvent.Set();Linguagem de código:  C#  ( cs )

O Set()método altera o estado do AutoResetEventpara sinalizado. Como resultado, a thread em espera (t) é liberada e continua a execução até a próxima chamada do WaitOne()método.

Assim que o thread for liberado, ele AutoResetEventserá automaticamente redefinido para o estado Não sinalizado.

Observe que o AutoResetEventserá redefinido automaticamente após liberar um único thread em espera. Para liberar vários threads em espera, você precisa chamar o Set()método para cada thread em espera ou usar a ManualResetEventclasse.

Exemplo de classe AutoResetEvent em C#

O programa a seguir demonstra como AutoResetEventfunciona:

using static System.Console;

var autoResetEvent = new AutoResetEvent(false);

void DoWork()
{
    WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is waiting for the event to be signaled...");

    // Wait for the event to be signaled
    autoResetEvent.WaitOne();

    WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} has been signaled and has resumed execution.");
}

// Create a thread that wait for the event to be signaled and start it
var t = new Thread(() => DoWork());
t.Start();

// Wait for 1s to let the thread runs for a while 
Thread.Sleep(1000);

// Wait for 2s before signaling the event
WriteLine("Waiting for 2 seconds before signaling the event...");
Thread.Sleep(2000);


// Signal the event
autoResetEvent.Set();

// Wait for the threads to finish
t.Join();

WriteLine("Press any key to exit.");
ReadKey();Linguagem de código:  C#  ( cs )

Como funciona.

Primeiro, crie um novo AutoResetEventobjeto e inicialize-o com false, denotando que o evento não foi sinalizado inicialmente:

var autoResetEvent = new AutoResetEvent(false);Linguagem de código:  C#  ( cs )

Segundo, defina o DoWork()método que representa a operação que um thread irá realizar:

void DoWork()
{
    WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is waiting for the event to be signaled...");

    // Wait for the event to be signaled
    autoResetEvent.WaitOne();

    WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} has been signaled and has resumed execution.");
}Linguagem de código:  C#  ( cs )

O DoWork()método grava uma mensagem no console indicando que a thread está aguardando a sinalização do evento. Em seguida, ele chama o WaitOne()método do AutoResetEventobjeto para aguardar a sinalização do evento.

O WaitOne()método bloqueia o thread que executa o DoWork()método até que o AutoResetEventobjeto seja sinalizado.

Quando for AutoResetEventsinalizado, o método retoma sua execução que grava outra mensagem no console.

Terceiro, crie e inicie um novo thread que execute o DoWork()método:

var t = new Thread(() => DoWork());
t.Start();Linguagem de código:  C#  ( cs )

Quarto, espere um segundo para deixar tempo suficiente para o thread t ser executado até que o WaitOne()método seja chamado:

Thread.Sleep(1000);Linguagem de código:  C#  ( cs )

Quinto, escreva uma mensagem no console e aguarde dois segundos antes de sinalizar o evento:

WriteLine("Waiting for 2 seconds before signaling the event...");
Thread.Sleep(2000);Linguagem de código:  C#  ( cs )

Sexto, altere o estado do AutoResetEventobjeto a ser sinalizado chamando o Set()método do AutoResetEventobjeto:

autoResetEvent.Set();Linguagem de código:  C#  ( cs )

Neste momento, a thread que executa o DoWorkretoma sua execução e exibe uma mensagem para o console.

Sétimo, aguarde a conclusão do thread chamando o Join()método da classe Thread:

t.Join();Linguagem de código:  C#  ( cs )

Por fim, espere que o usuário pressione qualquer tecla para sair do programa:

WriteLine("Press any key to exit.");
ReadKey();Linguagem de código:  C#  ( cs )

O exemplo a seguir mostra a saída do programa:

Thread 9 is waiting for the event to be signaled...
Waiting for 2 seconds before signaling the event...
Thread 9 has been signaled and has resumed execution.
Press any key to exit.Linguagem de código:  C#  ( cs )

Resumo

  • Use a AutoResetEventclasse C# para sincronizar threads e controlar suas execuções sinalizando eventos entre eles.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *