¿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!

TK
fuente
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.

Isak Savo
fuente
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).

Marcel Toth
fuente
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.

Joel Coehoorn
fuente
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.

Toni Petrina
fuente
¿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
31

Usa este código

using System.Threading;
// ...
Thread.Sleep(50);
Alexander Prokofyev
fuente
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
SelvirK
fuente
5

Para facilitar la lectura:

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

A partir de .NET Framework 4.5, puede usar:

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms
timmebee
fuente
-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);
    }
Akumaburn
fuente