¿Cuál es el impacto de Thread.Sleep (1) en C #?

En una aplicación de Windows, ¿cuál es el impacto de llamar a Thread.Sleep(1) como se ilustra en el siguiente código?

 public Constructor() { Thread thread = new Thread(Task); thread.IsBackground = true; thread.Start(); } private void Task() { while (true) { // do something Thread.Sleep(1); } } 

¿Este hilo acaparará toda la CPU disponible?

¿Qué técnicas de creación de perfiles puedo usar para medir el uso de la CPU de este subproceso (que no sea el administrador de tareas)?

Como se indicó, su bucle no enganchará a la CPU.

Pero tenga cuidado : Windows no es un sistema operativo en tiempo real, por lo que no obtendrá 1000 estelas por segundo de Thread.Sleep (1). Si no ha utilizado timeBeginPeriod para establecer su resolución mínima, se activará cada 15 ms. Incluso después de establecer la resolución mínima en 1 ms, solo se despertará cada 3-4 ms.

Para obtener la granularidad del temporizador de nivel de milisegundos, debe usar el temporizador multimedia Win32 ( contenedor C # ).

No, no acaparará la CPU, solo detendrá el hilo por al menos ese tiempo. Mientras el hilo está en pausa, el sistema operativo puede progtwigr otro hilo no relacionado para hacer uso del procesador.

Thread.Sleep (1) como se indica no enganchará a la CPU.

Esto es lo que sucede cuando un hilo duerme (más o menos):

  • Thread.Sleep se traduce en una llamada al sistema, que a su vez desencadena una trampa (una interrupción que permite que el sistema operativo tome el control)
  • El sistema operativo detecta la llamada a dormir y marca el hilo como bloqueado.
  • Internamente, el sistema operativo mantiene una lista de hilos que deben ser reactivados y cuándo debería suceder.
  • Como el hilo ya no usa la CPU, el sistema operativo …
  • Si el proceso principal no ha agotado todo su segmento de tiempo, el sistema operativo progtwigrá otra secuencia del proceso para su ejecución.
  • De lo contrario, otro proceso (o el proceso inactivo) comenzará a ejecutarse.
  • Cuando llegue el momento, su hilo será progtwigdo nuevamente para su ejecución, eso no significa que comenzará a ejecutarse automáticamente.

En una nota final, no sé exactamente lo que estás haciendo, pero parece que estás tratando de tomar el rol del progtwigdor, es decir, dormir para darle tiempo a la CPU para hacer otras cosas …

En algunos casos (muy pocos en verdad) podría estar bien, pero principalmente debe dejar que el planificador haga su trabajo, probablemente sepa más de lo que usted hace , y puede hacer el trabajo mejor de lo que puede hacerlo .

Como Bob Nadler mencionó Thread.Sleep(1) no garantiza un tiempo de espera de 1 ms.

Aquí hay un ejemplo usando el temporizador multimedia Win32 para forzar un sueño de 1ms.

  [DllImport("winmm.dll")] internal static extern uint timeBeginPeriod(uint period); [DllImport("winmm.dll")] internal static extern uint timeEndPeriod(uint period); timeBeginPeriod(1); while(true) { Thread.Sleep(1); // will sleep 1ms every time } timeEndPeriod(1); 

Al probar esto en una aplicación de GUI de C #, descubrí que la aplicación usaba aproximadamente el 50% de mi CPU.

Para obtener más información sobre este tema, consulte el siguiente hilo del foro:

http://www.dotnet247.com/247reference/msgs/57/289291.aspx

Deben evitarse tiempos de suspensión pequeños, ya que un hilo que renuncie a su segmento de tiempo recibe un refuerzo de prioridad cuando se lo retira, y eso puede conducir a altos cambios de contexto. En una aplicación multiproceso / servidor, esto puede llevar a un efecto contundente ya que los hilos están batallando por el tiempo de la CPU. En cambio, confíe en funciones asincrónicas y objetos de sincronización como secciones críticas o mutexes / semáforos.

Este es un hilo antiguo que aparece en muchas de mis búsquedas, pero Win7 tiene un nuevo progtwigdor y parece comportarse de manera diferente a la anterior.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { DateTime dtEnd = DateTime.Now.AddSeconds(1.0); int i = 0; while (DateTime.Now < dtEnd) { i++; Thread.Sleep(1); } Console.WriteLine(i.ToString()); i = 0; long lStart = DateTime.Now.Ticks; while (i++ < 1000) Thread.Sleep(1); long lTmp = (DateTime.Now.Ticks - lStart) / 10000; Console.WriteLine(lTmp.ToString()); Console.Read(); } } } 

Con el código anterior, Mi primer resultado dio 946. Así que en el intervalo de tiempo de 1 segundo usando 1ms duerme, obtuve 946 wake ups. Eso es muy cerca de 1 ms.

La segunda parte pregunta cuánto tiempo lleva hacer 1000 eventos de sueño a 1 ms cada uno. Tengo 1034ms. De nuevo, casi 1ms.

Esto estaba en un 1.8ghz core2duo + Win7 usando .Net 4.0

Editar: recuerde, dormir (x) no significa despertarse en este momento, significa no despertarme antes de esta vez. No está garantizado Aunque puede boost la prioridad del subproceso y Windows debe progtwigr el subproceso antes de los subprocesos de menor prioridad.

No, no acaparará toda la CPU disponible, ya que el progtwigdor del SO cambiará el hilo que duerme cuando otro hilo tiene trabajo pendiente.

No, no lo hará. Apenas lo verás En algún lugar menos de 1000 veces por segundo este hilo se despertará y no hará casi nada antes de volver a dormir.

Editar:

Tenía que verificar. Ejecutando en Java 1.5, esta prueba

 @Test public void testSpeed() throws InterruptedException { long currentTime = System.currentTimeMillis(); int i = 0; while (i < 1000) { Thread.sleep(1); i++; } System.out.println("Executed in " + (System.currentTimeMillis() - currentTime)); } 

Ran en aproximadamente 500 duerme por segundo en mi máquina 3ghz. Supongo que C # debería ser bastante similar. Supongo que alguien informará con números de C # para este punto de referencia intensamente importante en el mundo real. No hubo uso de CPU observable, por cierto.

Un hilo puede, como máximo, encerrar una CPU (lógica) a la vez. Y un sueño de 1ms no será acaparador. No te preocupes

también eche un vistazo a esto: foro msdn

 using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; namespace Test { public static class Program { public static void Main(string[] args) { Stopwatch sw = new Stopwatch(); for (int i = 0; i < 10; ++i) { sw.Reset(); sw.Start(); Thread.Sleep(50); sw.Stop(); Console.WriteLine("(default) Slept for " + sw.ElapsedMilliseconds); TimeBeginPeriod(1); sw.Reset(); sw.Start(); Thread.Sleep(50); sw.Stop(); TimeEndPeriod(1); Console.WriteLine("(highres) Slept for " + sw.ElapsedMilliseconds + "\n"); } } [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); } }