Temporizadores
.NET proporciona tres temporizadores que se pueden usar en un entorno multiproceso:
- System.Threading.Timer, que ejecuta un único método de devolución de llamada en un subproceso ThreadPool a intervalos regulares.
- System.Timers.Timer, que de forma predeterminada genera un evento en un subproceso ThreadPool a intervalos regulares.
- System.Threading.PeriodicTimer, lo que permite al autor de la llamada realizar el trabajo después de esperar tics individuales del temporizador.
Nota
Algunas implementaciones de .NET pueden incluir temporizadores adicionales:
- System.Windows.Forms.Timer: un componente de Windows Forms que produce un evento a intervalos regulares. El componente no tiene interfaz de usuario y está diseñado para su uso en un entorno de un único subproceso.
- System.Web.UI.Timer: un componente de ASP.NET que realiza postbacks de página web asincrónicos o sincrónicos en un intervalo definido.
- System.Windows.Threading.DispatcherTimer: un temporizador que se integra en la cola de Dispatcher que se procesa en un intervalo de tiempo especificado y con una prioridad especificada.
La clase System.Threading.Timer
La clase System.Threading.Timer permite llamar de forma continua a un delegado en intervalos de tiempo especificados. Esta clase también se puede usar para programar una sola llamada a un delegado en un intervalo de tiempo especificado. El delegado se ejecuta en un subproceso ThreadPool.
Cuando se crea un objeto System.Threading.Timer, se especifica un delegado TimerCallback que define el método de devolución de llamada, un objeto de estado opcional que se pasa a la devolución de llamada, la cantidad de tiempo de retraso antes de la primera invocación de la devolución de llamada y el intervalo de tiempo entre las invocaciones de devolución de llamada. Para cancelar un temporizador pendiente, llame a la función Timer.Dispose.
En el ejemplo siguiente se crea un temporizador que llama al delegado proporcionado por primera vez después de un segundo (1000 milisegundos) y, después, lo llama cada dos segundos. El objeto de estado del ejemplo se usa para contar el número de veces que se llama al delegado. El temporizador se detiene cuando el delegado se ha llamado al menos 10 veces.
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 obtener más información y ejemplos, vea System.Threading.Timer.
La clase System.Timers.Timer
Otro temporizador que se puede usar en un entorno multiproceso es System.Timers.Timer que, de forma predeterminada, genera un evento en un subproceso ThreadPool.
Cuando se crea un objeto System.Timers.Timer, se puede especificar el intervalo de tiempo en el que se va a generar un evento Elapsed. Use la propiedad Enabled para indicar si un temporizador debe generar un evento Elapsed. Si necesita que un evento Elapsed se genere solo una vez cuando haya transcurrido el intervalo especificado, establezca AutoReset en false
. El valor predeterminado de la propiedad AutoReset es true
, lo que significa que un evento Elapsed se genera periódicamente durante el intervalo definido por la propiedad Interval.
Para obtener más información y ejemplos, vea System.Timers.Timer.
Clase System.Threading.PeriodicTimer
La clase System.Threading.PeriodicTimer permite esperar tics individuales de un intervalo especificado, realizando el trabajo después de llamar a PeriodicTimer.WaitForNextTickAsync.
Al crear un objeto System.Threading.PeriodicTimer, se especifica un objeto TimeSpan que determina el periodo de tiempo entre cada tic del temporizador. En lugar de pasar una devolución de llamada o establecer un controlador de eventos como en las clases del temporizador anteriores, se realiza el trabajo directamente en el ámbito, esperando a WaitForNextTickAsync para avanzar el temporizador por el intervalo especificado.
El método WaitForNextTickAsync devuelve un elemento ValueTask<bool>
; true
tras la activación correcta del temporizador y false
cuando el temporizador se ha cancelado llamando a PeriodicTimer.Dispose. WaitForNextTickAsync opcionalmente acepta un elemento CancellationToken, lo que da como resultado un elemento TaskCanceledException cuando se ha solicitado una cancelación.
Para obtener más información, vea System.Threading.PeriodicTimer.