Resumo : neste tutorial, você aprenderá como usar a AutoResetEvent
classe C# para sincronizar threads e controlar suas execuções sinalizando eventos entre elas.
Introdução à classe C# AutoResetEvent
A AutoResetEvent
classe permite que vários threads se comuniquem entre si sinalizando eventos.
An AutoResetEvent
tem dois estados:
- Sinalizado
- Não sinalizado
Quando um AutoResetEvent
objeto é sinalizado, um único thread em espera será liberado e continuará sua execução.
No entanto, quando um
objeto é Unsignaled, o thread em espera será bloqueado até que AutoResetEvent
seja sinalizado novamente.AutoResetEvent
O AutoResetEvent
objeto possui dois métodos principais que controlam seu estado: Waitone()
e Set()
:
- O
WaitOne()
método bloqueia o thread atual até queAutoResetEvent
seja sinalizado ou um intervalo de tempo limite tenha decorrido. - O
Set()
método mudou o estado paraAutoResetEvent
não sinalizado e libera um único thread em espera.
Na prática, você usa o AutoResetEvent
em 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 AutoResetEvent
classe, você pode seguir estas etapas:
Primeiro, crie um AutoResetEvent
objeto:
var autoResetEvent = new AutoResetEvent(false);
Linguagem de código: C# ( cs )
O parâmetro false define o estado do AutoResetEvent
objeto 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 AutoResetEvent
chamando o Set()
método:
autoResetEvent.Set();
Linguagem de código: C# ( cs )
O Set()
método altera o estado do AutoResetEvent
para 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 AutoResetEvent
será automaticamente redefinido para o estado Não sinalizado.
Observe que o AutoResetEvent
será 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 ManualResetEvent
classe.
Exemplo de classe AutoResetEvent em C#
O programa a seguir demonstra como AutoResetEvent
funciona:
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 AutoResetEvent
objeto 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 AutoResetEvent
objeto para aguardar a sinalização do evento.
O WaitOne()
método bloqueia o thread que executa o DoWork()
método até que o AutoResetEvent
objeto seja sinalizado.
Quando for AutoResetEvent
sinalizado, 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
objeto a ser sinalizado chamando o AutoResetEvent
Set()
método do
objeto:AutoResetEvent
autoResetEvent.Set();
Linguagem de código: C# ( cs )
Neste momento, a thread que executa o DoWork
retoma 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
AutoResetEvent
classe C# para sincronizar threads e controlar suas execuções sinalizando eventos entre eles.