¿Cómo hago para que mi programa C # duerma durante 50 ms?


272

¿Cómo hago para que mi programa C # duerma durante 50 milisegundos?

Puede parecer una pregunta fácil, ¡pero estoy teniendo un momento de insuficiencia cerebral temporal!


1
Vuelva a etiquetar a VB.NET ya que la respuesta también funciona allí.
DrFloyd5

No DrFloyd5; no funciona en VB.NET, ¿verdad?
Zanoni

16
Si estuviera en el equipo de VB.Net, agregaría; como personaje de comentario para la próxima versión del lenguaje ...
Joel Coehoorn

44
Creo que los programadores de VB son lo suficientemente brillantes como para descubrir el equivalente ..
BlueRaja - Danny Pflughoeft

bueno, solo para asegurarse, ahora no tienen que hacerlo.
PsychoData

Respuestas:


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

Sin embargo, recuerde que hacer esto en el hilo principal de la GUI bloqueará la actualización de su GUI (se sentirá "lenta")

Simplemente elimine ;para que funcione también para VB.net.


Después de llamar a dormir en un método, ¿el programa continuará ejecutándose en segundo plano (sin crear un nuevo hilo)? Además, si llamo a dormir en un nuevo hilo, ¿continuará el hilo principal su trabajo?
Jay Nirgudkar

@JayNirgudkar se detendrá el hilo que llama Sleep. Otros hilos no se ven afectados.
Isak Savo

No se garantiza que esto sea exacto.
Akumaburn

150

Básicamente hay 3 opciones para esperar (casi) cualquier lenguaje de programación:

  1. Espera floja
    • Ejecutar bloques de subprocesos durante un tiempo determinado (= no consume potencia de procesamiento)
    • No es posible procesar el hilo bloqueado / en espera
    • No tan preciso
  2. Espera apretada (también llamada lazo cerrado)
    • el procesador está MUY ocupado durante todo el intervalo de espera (de hecho, generalmente consume el 100% del tiempo de procesamiento de un núcleo)
    • Algunas acciones se pueden realizar mientras se espera
    • Muy preciso
  3. Combinación de 2 anteriores
    • Por lo general, combina una eficiencia de procesamiento de 1. y precisión + capacidad para hacer algo de 2.

para 1. - Suelta esperando en C #:

Thread.Sleep(numberOfMilliseconds);

Sin embargo, el programador de subprocesos de Windows hace que la precisión Sleep()sea ​​de alrededor de 15 ms (por lo que el modo de suspensión puede esperar fácilmente 20 ms, incluso si está programado para esperar solo 1 ms).

para 2. - La espera apretada en C # es:

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

También podríamos usar DateTime.Nowu otros medios de medición del tiempo, pero Stopwatches mucho más rápido (y esto realmente se haría visible en un circuito cerrado).

para 3. - Combinación:

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
}

Este código bloquea regularmente el subproceso durante 1 ms (o un poco más, según la programación del subproceso del sistema operativo), por lo que el procesador no está ocupado durante ese tiempo de bloqueo y el código no consume el 100% de la potencia del procesador. Todavía se puede realizar otro procesamiento en el bloqueo intermedio (como: actualización de la interfaz de usuario, manejo de eventos o interacción / comunicación).


1
El temporizador también puede ser de interés
JonnyRaa

55

No puede especificar un tiempo de suspensión exacto en Windows. Necesitas un sistema operativo en tiempo real para eso. Lo mejor que puede hacer es especificar un tiempo mínimo de sueño. Luego, depende del planificador activar su hilo después de eso. Y nunca llame .Sleep()al hilo GUI.


44

Como ahora tiene la función async / wait, la mejor manera de dormir durante 50 ms es mediante Task.Delay:

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

O si está apuntando a .NET 4 (con Async CTP 3 para VS2010 o Microsoft.Bcl.Async), debe usar:

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

De esta manera no bloqueará el hilo de la interfaz de usuario.


¿Puede responder. enjuague durante este retraso, si está en un bucle?
Teoman shipahi

No, no puedes. Creo que hay una FlushAsyncversión.
Toni Petrina

66
Una alternativa que no requiere una asyncdeclaración es llamarTask.Delay(50).Wait();
stuartd


14
Thread.Sleep(50);

El subproceso no se programará para su ejecución por el sistema operativo durante el tiempo especificado. Este método cambia el estado del hilo para incluir WaitSleepJoin.

Este método no realiza el bombeo estándar de COM y SendMessage. Si necesita dormir en un subproceso que tiene STAThreadAttribute, pero desea realizar un bombeo COM y SendMessage estándar, considere usar una de las sobrecargas del método Join que especifica un intervalo de tiempo de espera.

Thread.Join

5

Para facilitar la lectura:

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

0

A partir de .NET Framework 4.5, puede usar:

using System.Threading.Tasks;

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

-1

Lo mejor de ambos 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);
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.