HOWTO · Csharp

Come creare un timer di ritardo in C#

Questo articolo introduce come creare un timer di ritardo in C#. Include quattro metodi diversi: Thread.Sleep(), Task.Delay(), System.Timers.Timer e System.Threading.Timer.

In questa pagina

Per aggiungere un ritardo in C#, scegli Thread.Sleep() per bloccare il thread corrente, Task.Delay() per attendere in modo asincrono oppure una classe timer per pianificare un callback. Gli esempi seguenti utilizzano un intervallo di due secondi e mostrano come si comporta ciascuna opzione. Non sono stati eseguiti nel runtime fornito, quindi non viene dichiarato alcun output osservato.

Usare il metodo Thread.Sleep() per creare un ritardo in C#

Thread.Sleep() mette in pausa il thread corrente per il numero specificato di millisecondi. Poiché quel thread non può svolgere altro lavoro durante l’attesa, usa questo approccio solo quando il blocco è appropriato, ad esempio in un breve programma console sincrono.

Questo esempio completo stampa un messaggio, attende due secondi e poi stampa un altro messaggio:

using System;
using System.Threading;

class DelayExample
{
    static void Main()
    {
        Console.WriteLine("The delay starts.");
        Thread.Sleep(2000);
        Console.WriteLine("The delay ends.");
    }
}

L’argomento è in millisecondi, quindi 2000 richiede un’attesa di due secondi. Il tempo effettivamente trascorso può variare in base alla pianificazione del sistema.

Usare il metodo Task.Delay() per creare un ritardo in C#

Task.Delay() crea un’attività che si completa dopo l’intervallo richiesto. Attenderla con await in un metodo asincrono consente a quel metodo di cedere durante l’attesa, a differenza di Thread.Sleep(), che occupa il thread corrente. Chiama il metodo asincrono dal flusso asincrono esistente della tua applicazione.

Questo esempio completo mantiene l’attesa asincrona in un metodo separato e utilizza un punto di ingresso sincrono per chiamarlo:

using System;
using System.Threading.Tasks;

class DelayExample
{
    static void Main()
    {
        RunAsync().GetAwaiter().GetResult();
    }

    static async Task RunAsync()
    {
        Console.WriteLine("Before the delay");
        await Task.Delay(2000);
        Console.WriteLine("After the delay");
    }
}

L’espressione await riprende RunAsync dopo il completamento dell’attività di ritardo. In un’applicazione che utilizza già metodi asincroni, attendi direttamente Task.Delay(2000) con await invece di bloccare il punto di ingresso per attendere l’attività.

Usare la classe System.Timers.Timer per creare un ritardo in C#

System.Timers.Timer genera un evento Elapsed dopo il suo Interval in millisecondi. Imposta AutoReset su false per un singolo evento; impostalo su true quando l’evento deve ripetersi all’intervallo. Il callback è guidato dagli eventi, quindi l’avvio di un timer non mette in pausa la riga di codice successiva.

Questo esempio completo attende l’evento singolo prima che il programma console termini:

using System;
using System.Threading;
using System.Timers;

class DelayExample
{
    static void Main()
    {
        using (var completed = new ManualResetEvent(false))
        using (var timer = new System.Timers.Timer(2000))
        {
            timer.AutoReset = false;
            timer.Elapsed += (sender, args) =>
            {
                Console.WriteLine("Timer elapsed.");
                completed.Set();
            };

            Console.WriteLine("Timer started.");
            timer.Start();
            completed.WaitOne();
        }
    }
}

WaitOne() mantiene attivo questo esempio console finché il gestore dell’evento non segnala il completamento. In un’applicazione di più lunga durata, mantieni l’applicazione attiva in base al suo normale ciclo di eventi o alla durata del servizio, invece di aggiungere un’attesa bloccante solo per il timer.

Usare la classe System.Threading.Timer per creare un ritardo in C#

System.Threading.Timer pianifica un callback con un tempo di scadenza iniziale e un periodo. Entrambi i valori sono in millisecondi. Usa Timeout.Infinite per il periodo quando il callback deve essere eseguito una sola volta; fornisci un periodo finito per pianificare callback ripetuti. Il callback viene eseguito separatamente dal codice che avvia il timer.

Questo esempio completo pianifica un callback dopo due secondi e lo attende prima di terminare:

using System;
using System.Threading;

class DelayExample
{
    static void Main()
    {
        using (var completed = new ManualResetEvent(false))
        using (var timer = new System.Threading.Timer(
            state =>
            {
                Console.WriteLine("Timer callback.");
                completed.Set();
            },
            null,
            2000,
            Timeout.Infinite))
        {
            Console.WriteLine("Timer scheduled.");
            completed.WaitOne();
        }
    }
}

Il tempo di scadenza pianifica il primo callback due secondi dopo la costruzione. Timeout.Infinite impedisce la pianificazione di un altro callback. L’attesa mantiene attivo questo esempio console abbastanza a lungo da ricevere il callback; un’applicazione con un proprio ciclo di eventi può utilizzare invece quella durata.

Conclusione

Usa Thread.Sleep() per una semplice pausa sincrona quando bloccare il thread corrente è accettabile. Preferisci Task.Delay() con await nel codice asincrono in modo che il metodo possa cedere durante l’attesa. Scegli System.Timers.Timer o System.Threading.Timer quando hai bisogno di una pianificazione basata su callback, con AutoReset o il periodo del timer a controllare la ripetizione. I callback dei timer pianificano il lavoro; non mettono in pausa l’esecuzione sequenziale e la loro temporizzazione non è una garanzia esatta dell’orologio reale.