Como faço para meu programa C # dormir por 50 mseg?

272

Como faço para meu programa C # dormir por 50 milissegundos?

Pode parecer uma pergunta fácil, mas estou tendo um momento temporário de insuficiência cerebral!

TK.
fonte
1
Re-marcado para VB.NET como a resposta funciona lá também.
precisa saber é o seguinte
Não DrFloyd5; não funciona no VB.NET, certo?
Zanoni
16
Se eu estivesse na equipe do VB.Net, acrescentaria; como um caractere de comentário para a próxima versão da linguagem ...
Joel Coehoorn
4
Eu acho que os programadores VB é brilhante o suficiente para descobrir o equivalente ..
BlueRaja - Danny Pflughoeft
bem, só para ter certeza, agora eles não precisam.
PsychoData

Respostas:

330
System.Threading.Thread.Sleep(50);

Lembre-se, porém, que fazer isso no thread principal da GUI impedirá a atualização da GUI (ela parecerá "lenta")

Basta remover o ;para fazê-lo funcionar no VB.net também.

Isak Savo
fonte
Após chamar a suspensão em um método, o programa continuará sendo executado em segundo plano (sem criar novo encadeamento)? Além disso, se eu chamar suspensão em um novo thread, o thread principal continuará seu trabalho?
Jay Nirgudkar
@JayNirgudkar, o segmento que chama Sleep será interrompido. Outros threads não são afetados.
Isak Savo 28/05
Não é garantido que isso seja preciso.
Akumaburn 28/10
150

Existem basicamente três opções para aguardar (quase) em qualquer linguagem de programação:

  1. Espera solta
    • Executando blocos de encadeamento por um tempo determinado (= não consome poder de processamento)
    • Nenhum processamento é possível no encadeamento bloqueado / em espera
    • Não é tão preciso
  2. Espera apertada (também chamada de loop apertado)
    • O processador fica MUITO ocupado durante todo o intervalo de espera (na verdade, geralmente consome 100% do tempo de processamento de um núcleo)
    • Algumas ações podem ser executadas enquanto aguarda
    • Muito preciso
  3. Combinação dos 2 anteriores
    • Geralmente, combina eficiência de processamento de 1. e precisão + capacidade de fazer algo de 2.

para 1. - Espera solta em C #:

Thread.Sleep(numberOfMilliseconds);

No entanto, o agendador de encadeamentos do Windows faz com que a precisão Sleep()fique em torno de 15ms (para que o Sleep possa esperar facilmente por 20ms, mesmo que agendado para esperar apenas por 1ms).

para 2. - A espera apertada em C # é:

Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
    //some other processing to do possible
    if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
    {
        break;
    }
}

Também poderíamos usar DateTime.Nowou outros meios de medição de tempo, mas Stopwatché muito mais rápido (e isso realmente se tornaria visível em loop apertado).

para 3. - Combinação:

Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
    //some other processing to do STILL POSSIBLE
    if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
    {
        break;
    }
    Thread.Sleep(1); //so processor can rest for a while
}

Esse código bloqueia regularmente o encadeamento por 1ms (ou um pouco mais, dependendo do agendamento do encadeamento do SO), para que o processador não fique ocupado durante esse período de bloqueio e o código não consuma 100% da energia do processador. Outro processamento ainda pode ser realizado entre os bloqueios (como: atualização da interface do usuário, manipulação de eventos ou interação / comunicação).

Marcel Toth
fonte
1
Temporizador também pode ser de interesse
JonnyRaa
55

Você não pode especificar um tempo exato de suspensão no Windows. Você precisa de um sistema operacional em tempo real para isso. O melhor que você pode fazer é especificar um tempo mínimo de sono. Depois, cabe ao agendador ativar seu encadeamento depois disso. E nunca chame .Sleep()o thread da GUI.

Joel Coehoorn
fonte
44

Como agora você tem o recurso assíncrono / espera, a melhor maneira de dormir por 50ms é usando o Task.Delay:

async void foo()
{
    // something
    await Task.Delay(50);
}

Ou, se você estiver direcionando o .NET 4 (com Async CTP 3 para VS2010 ou Microsoft.Bcl.Async), use:

async void foo()
{
    // something
    await TaskEx.Delay(50);
}

Dessa forma, você não bloqueará o thread da interface do usuário.

Toni Petrina
fonte
você pode response.flush durante esse atraso, se estiver em um loop?
Teoman shipahi
Não, você não pode. Eu acredito que há uma FlushAsyncversão.
Toni Petrina
6
Uma alternativa que não requer uma asyncdeclaração é chamarTask.Delay(50).Wait();
stuartd
31

Use este código

using System.Threading;
// ...
Thread.Sleep(50);
Alexander Prokofyev
fonte
14
Thread.Sleep(50);

O encadeamento não será agendado para execução pelo sistema operacional pela quantidade de tempo especificada. Este método altera o estado do thread para incluir WaitSleepJoin.

Esse método não executa o bombeamento COM e SendMessage padrão. Se você precisar dormir em um encadeamento que possui STAThreadAttribute, mas deseja executar o bombeamento COM e SendMessage padrão, considere usar uma das sobrecargas do método Join que especifica um intervalo de tempo limite.

Thread.Join
SelvirK
fonte
5

Para legibilidade:

using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
Coronel Panic
fonte
0

A partir do .NET Framework 4.5, você pode usar:

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms
timmebee
fonte
-1

Melhor dos dois mundos:

using System.Runtime.InteropServices;

    [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod", SetLastError = true)]
    private static extern uint TimeBeginPeriod(uint uMilliseconds);

    [DllImport("winmm.dll", EntryPoint = "timeEndPeriod", SetLastError = true)]
    private static extern uint TimeEndPeriod(uint uMilliseconds);
    /**
     * Extremely accurate sleep is needed here to maintain performance so system resolution time is increased
     */
    private void accurateSleep(int milliseconds)
    {
        //Increase timer resolution from 20 miliseconds to 1 milisecond
        TimeBeginPeriod(1);
        Stopwatch stopwatch = new Stopwatch();//Makes use of QueryPerformanceCounter WIN32 API
        stopwatch.Start();

        while (stopwatch.ElapsedMilliseconds < milliseconds)
        {
            //So we don't burn cpu cycles
            if ((milliseconds - stopwatch.ElapsedMilliseconds) > 20)
            {
                Thread.Sleep(5);
            }
            else
            {
                Thread.Sleep(1);
            }
        }

        stopwatch.Stop();
        //Set it back to normal.
        TimeEndPeriod(1);
    }
Akumaburn
fonte