Temporizadores
O .NET fornece três temporizadores a serem usados em um ambiente multi-threaded:
- System.Threading.Timer, que executa um único método de retorno de chamada em um thread ThreadPool em intervalos regulares.
- System.Timers.Timer, que por padrão gera um evento em um thread ThreadPool em intervalos regulares.
- System.Threading.PeriodicTimer, que permite que o autor da chamada execute o trabalho depois de aguardar tiques individuais do temporizador.
Observação
Algumas implementações do .NET podem incluir temporizadores adicionais:
- System.Windows.Forms.Timer: um componente do Windows Forms que dispara um evento em intervalos regulares. O componente não tem nenhuma interface do usuário e é projetado para ser usado em um ambiente single-threaded.
- System.Web.UI.Timer: um componente do ASP.NET que executa postbacks de página da Web assíncrona ou síncrona em intervalos regulares.
- System.Windows.Threading.DispatcherTimer: um temporizador que é integrado à fila Dispatcher que é processada em um intervalo de tempo especificado e com uma prioridade especificada.
A classe System.Threading.Timer
A classe System.Threading.Timer permite chamar um delegado continuamente em intervalos de tempo especificado. Você também pode usar essa classe para agendar uma única chamada para um representante em um intervalo de tempo especificado. O delegado é executado em um thread ThreadPool.
Ao criar um objeto System.Threading.Timer, você especifica um delegado TimerCallback que define o método de retorno de chamada, um objeto de estado opcional que é passado para o retorno de chamada, o período de atraso antes da primeira invocação do retorno de chamada e o intervalo de tempo entre as invocações do retorno de chamada. Para cancelar um temporizador pendente, chame o método Timer.Dispose.
O exemplo a seguir cria um temporizador que chama o delegado fornecido pela primeira vez após um segundo (1000 milissegundos) e, em seguida, chama a cada dois segundos. O objeto de estado no exemplo é usado para contar quantas vezes o delegado é chamado. O temporizador é interrompido quando o delegado é chamado pelo menos 10 vezes.
using namespace System;
using namespace System::Threading;
ref class TimerState
{
public:
int counter;
};
ref class Example
{
private:
static Timer^ timer;
public:
static void TimerTask(Object^ state)
{
Console::WriteLine("{0:HH:mm:ss.fff}: starting a new callback.", DateTime::Now);
TimerState^ timerState = dynamic_cast<TimerState^>(state);
Interlocked::Increment(timerState->counter);
}
static void Main()
{
TimerCallback^ tcb = gcnew TimerCallback(&TimerTask);
TimerState^ state = gcnew TimerState();
state->counter = 0;
timer = gcnew Timer(tcb, state, 1000, 2000);
while (state->counter <= 10)
{
Thread::Sleep(1000);
}
timer->~Timer();
Console::WriteLine("{0:HH:mm:ss.fff}: done.", DateTime::Now);
}
};
int main()
{
Example::Main();
}
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
private static Timer timer;
static void Main(string[] args)
{
var timerState = new TimerState { Counter = 0 };
timer = new Timer(
callback: new TimerCallback(TimerTask),
state: timerState,
dueTime: 1000,
period: 2000);
while (timerState.Counter <= 10)
{
Task.Delay(1000).Wait();
}
timer.Dispose();
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: done.");
}
private static void TimerTask(object timerState)
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: starting a new callback.");
var state = timerState as TimerState;
Interlocked.Increment(ref state.Counter);
}
class TimerState
{
public int Counter;
}
}
Imports System.Threading
Module Program
Private Timer As Timer
Sub Main(args As String())
Dim StateObj As New TimerState
StateObj.Counter = 0
Timer = New Timer(New TimerCallback(AddressOf TimerTask), StateObj, 1000, 2000)
While StateObj.Counter <= 10
Task.Delay(1000).Wait()
End While
Timer.Dispose()
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: done.")
End Sub
Private Sub TimerTask(ByVal StateObj As Object)
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: starting a new callback.")
Dim State As TimerState = CType(StateObj, TimerState)
Interlocked.Increment(State.Counter)
End Sub
Private Class TimerState
Public Counter As Integer
End Class
End Module
Para obter mais informações e exemplos, consulte System.Threading.Timer.
A classe System.Timers.Timer
Outro temporizador que pode ser usado em um ambiente multi-threaded é o System.Timers.Timer que, por padrão, gera um evento em um thread ThreadPool.
Ao criar um objeto System.Timers.Timer, você pode especificar o intervalo de tempo em que um evento Elapsed deve ser gerado. Use a propriedade Enabled para indicar se um temporizador deve gerar um evento Elapsed. Se você precisar que um evento Elapsed seja gerado apenas uma vez depois que o intervalo especificado for decorrido, defina AutoReset para false
. O valor padrão da propriedade AutoReset é true
, o que significa que um evento Elapsed é gerado regularmente no intervalo definido pela propriedade Interval.
Para obter mais informações e exemplos, consulte System.Timers.Timer.
A classe System.Threading.PeriodicTimer
A classe System.Threading.PeriodicTimer permite que você aguarde tiques individuais de um intervalo especificado, executando o trabalho após chamar PeriodicTimer.WaitForNextTickAsync.
Ao criar um objeto System.Threading.PeriodicTimer, você especifica um TimeSpan que determina o período entre cada tique do temporizador. Em vez de passar um retorno de chamada ou definir um manipulador de eventos como nas classes de temporizador anteriores, você executa o trabalho diretamente no escopo, aguardando WaitForNextTickAsync para avançar o temporizador no intervalo especificado.
O método WaitForNextTickAsync retorna um ValueTask<bool>
; true
após o disparo bem-sucedido do temporizador e false
quando o temporizador foi cancelado chamando PeriodicTimer.Dispose. WaitForNextTickAsync opcionalmente aceita um CancellationToken, que resulta em um TaskCanceledException quando um cancelamento foi solicitado.
Para obter mais informações, consulte System.Threading.PeriodicTimer.