Temporizadores

.NET proporciona tres temporizadores que se pueden usar en un entorno multiproceso:

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.

Vea también