thread second pause form c# multithreading sleep stopwatch

c# - second - ¿Qué tan preciso es Thread.Sleep(TimeSpan)?



thread.sleep c# (6)

Dormir el hilo y la sincronización / regulación son cosas muy diferentes, y deben tratarse adecuadamente. Dormir un hilo es una tarea general, ya que permite al sistema dar a otros hilos y procesos la posibilidad de ejecutar sin ser específico al respecto. Por otro lado, la aceleración de una aplicación o la programación de tareas que necesitan una sincronización precisa deben realizarse con un temporizador explícito.

Tenga en cuenta que, si necesita procesos precisos en el tiempo o sincronización, tendrá dificultades para lograrlo con un proceso normal en Windows. Necesitaría utilizar las prioridades de Windows en tiempo real para lograr con éxito la sincronización o la aceleración, ya que las ventanas pueden dormir en cualquier hilo en cualquier momento si es precedida por otro hilo.

Me he encontrado con una prueba de unidad que está fallando de manera intermitente porque el tiempo transcurrido no es lo que espero que sea.

Un ejemplo de cómo se ve esta prueba es:

Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); TimeSpan oneSecond = new TimeSpan(0, 0, 1); for(int i=0; i<3; i++) { Thread.Sleep(oneSecond); } stopwatch.Stop(); Assert.GreaterOrEqual(stopwatch.ElapsedMilliseconds, 2999);

La mayoría de las veces esto pasa, pero ha fallado al menos en una ocasión porque:

Esperado: mayor o igual a 2999 Pero fue: 2998

No entiendo cómo podría ser menos de 3 segundos. ¿Hay algún problema de precisión con Thread.Sleep o tal vez con un cronómetro que no conozca?

Solo como una actualización de algunas de las preguntas a continuación. El escenario en el que se está probando la unidad es una clase que permite a uno llamar a un método para realizar alguna acción y, si falla, espera un segundo y recupera ese método. La prueba que se muestra arriba es solo una aproximación de lo que está sucediendo.

Digamos que quería llamar a un método DoSomething () ... pero en el caso de que DoSomething () lance una excepción, quiero poder volver a intentar llamar hasta un máximo de 3 veces, pero esperar 1 segundo entre cada intento. El objetivo de la prueba de la unidad, en este caso, es verificar que cuando solicitamos 3 reintentos con 1 segundo de espera entre cada reintento, el tiempo total tomado sea mayor a 3 segundos.


En una aplicación en la que quería dormir por al menos x milisegundos, usé un código similar a:

public void Sleep(int milliseconds) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); while (stopwatch.ElapsedMilliseconds < milliseconds) { int timeout = milliseconds - stopwatch.ElapsedMilliseconds; Thread.Sleep(timeout >= 0 ? timeout : 0); } stopwatch.Stop(); }

En respuesta a la precisión de Thread.Sleep, no es precisa en absoluto. Creo que la resolución está en algún lugar alrededor de 10 ms. No se garantiza que haga mucho de nada excepto ''aproximadamente'' este tiempo.


Experimentando rápidamente, me doy cuenta de que un fragmento de código como ...

do {Debug.WriteLine (DateTime.Now.TimeOfDay.TotalMilliseconds.ToString ()); } while (1);

muestra el mismo número varias veces, luego salta a un nuevo número que se muestra varias veces, etc. La brecha entre estos conjuntos de números es consistentemente de 15.625 ms, lo que observo es 1000/64.

Parece que los temporizadores de Windows tienen una granularidad de 1/64 de segundo. Si necesitas algo mejor que eso, entonces siento tu dolor, pero ese es el marco en el que debes encajar. (Windows no es un sistema operativo difícil en tiempo real y no pretende serlo).


Tal vez no debas confiar en el sesgo de tiempo para averiguar si has tenido éxito. Mejor cuente su número de intentos y evalúe contra esto:

int tries; for(tries=0; tries<3; tries++) { Thread.Sleep(oneSecond); } Assert.GreaterOrEqual(tries, 3);


Thread.Sleep no está diseñado para el despertar de precisión. Realmente, la arquitectura de Windows en sí no está diseñada para este tipo de cosas.


Tu hilo está compartiendo el tiempo de CPU con otros hilos. El Sleep terminará tan pronto como sea su turno y el kernel note que el tiempo de sleep ha transcurrido, por lo que no es tan preciso.

La carga de la CPU, las prioridades del proceso, la cantidad de subprocesos concurrentes, incluso de otros procesos, tendrán efecto sobre ella.