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!


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.


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).


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.


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.


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


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

5

Para legibilidade:

using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));

0

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

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms

-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);
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.