HOWTO · Csharp

Como fazer um temporizador de atraso em C#

Este artigo apresenta como fazer um temporizador de atraso em C#. Ele inclui quatro métodos diferentes: Thread.Sleep(), Task.Delay(), System.Timers.Timer e System.Threading.Timer.

Nesta página

Para adicionar um atraso em C#, escolha Thread.Sleep() para bloquear o thread atual, Task.Delay() para aguardar de forma assíncrona ou uma classe de temporizador para agendar um callback. Os exemplos abaixo usam um intervalo de dois segundos e mostram como cada opção se comporta. Eles não foram executados no runtime fornecido, portanto nenhuma saída observada é alegada.

Usar o método Thread.Sleep() para criar um atraso em C#

Thread.Sleep() pausa o thread atual pelo número especificado de milissegundos. Como esse thread não pode realizar outro trabalho durante a espera, use essa abordagem apenas quando o bloqueio for apropriado, como em um programa de console síncrono curto.

Este exemplo completo imprime uma mensagem, aguarda dois segundos e, em seguida, imprime outra mensagem:

using System;
using System.Threading;

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

O argumento está em milissegundos, portanto 2000 solicita uma espera de dois segundos. O tempo real decorrido pode variar de acordo com o agendamento do sistema.

Usar o método Task.Delay() para criar um atraso em C#

Task.Delay() cria uma tarefa que é concluída após o intervalo solicitado. Aguardá-la com await em um método assíncrono permite que esse método ceda enquanto espera, ao contrário de Thread.Sleep(), que ocupa o thread atual. Chame o método assíncrono a partir do fluxo assíncrono existente do seu aplicativo.

Este exemplo completo mantém a espera assíncrona em um método separado e usa um ponto de entrada síncrono para chamá-lo:

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");
    }
}

A expressão await retoma RunAsync após a conclusão da tarefa de atraso. Em um aplicativo que já usa métodos assíncronos, aguarde Task.Delay(2000) diretamente com await em vez de bloquear o ponto de entrada para aguardar a tarefa.

Usar a classe System.Timers.Timer para criar um atraso em C#

System.Timers.Timer gera um evento Elapsed após o seu Interval em milissegundos. Defina AutoReset como false para um único evento; defina-o como true quando o evento deve se repetir no intervalo. O callback é orientado a eventos, portanto iniciar um temporizador não pausa a próxima linha de código.

Este exemplo completo aguarda o evento único antes de o programa de console terminar:

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() mantém este exemplo de console ativo até que o manipulador de evento sinalize a conclusão. Em um aplicativo de execução mais longa, mantenha o aplicativo ativo de acordo com seu loop de eventos normal ou tempo de vida do serviço, em vez de adicionar uma espera bloqueante apenas para o temporizador.

Usar a classe System.Threading.Timer para criar um atraso em C#

System.Threading.Timer agenda um callback com um tempo de vencimento inicial e um período. Ambos os valores estão em milissegundos. Use Timeout.Infinite para o período quando o callback deve ser executado uma vez; forneça um período finito para agendar callbacks repetidos. O callback é executado separadamente do código que inicia o temporizador.

Este exemplo completo agenda um callback após dois segundos e o aguarda antes de terminar:

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();
        }
    }
}

O tempo de vencimento agenda o primeiro callback dois segundos após a construção. Timeout.Infinite impede que outro callback seja agendado. A espera mantém este exemplo de console ativo por tempo suficiente para receber o callback; um aplicativo com seu próprio loop de eventos pode usar esse tempo de vida.

Conclusão

Use Thread.Sleep() para uma pausa síncrona simples quando bloquear o thread atual for aceitável. Prefira Task.Delay() com await em código assíncrono para que o método possa ceder enquanto espera. Escolha System.Timers.Timer ou System.Threading.Timer quando precisar de agendamento baseado em callbacks, com AutoReset ou o período do temporizador controlando a repetição. Os callbacks de temporizador agendam trabalho; eles não pausam a execução sequencial, e seu tempo não é uma garantia exata de relógio de parede.