A menudo veo que se menciona que Thread.Sleep();
no debería usarse, pero no puedo entender por qué es así. Si Thread.Sleep();
puede causar problemas, ¿hay alguna solución alternativa con el mismo resultado que sea segura?
p.ej.
while(true)
{
doSomework();
i++;
Thread.Sleep(5000);
}
otro es:
while (true)
{
string[] images = Directory.GetFiles(@"C:\Dir", "*.png");
foreach (string image in images)
{
this.Invoke(() => this.Enabled = true);
pictureBox1.Image = new Bitmap(image);
Thread.Sleep(1000);
}
}
c#
multithreading
sleep
Burimi
fuente
fuente
goto:
es decir, que probablemente haya una mejor solución a sus problemas queSleep
.goto
, que se parece más a un olor a código que a un olor de diseño. No hay nada de malo en que un compilador insertegoto
s en su código: la computadora no se confunde. PeroThread.Sleep
no es exactamente lo mismo; los compiladores no insertan esa llamada y tiene otras consecuencias negativas. Pero sí, el sentimiento general de que usarlo es incorrecto porque casi siempre hay una mejor solución es ciertamente correcto.sleep()
código (o pruebas) muere un cachorroRespuestas:
Los problemas con las llamadas
Thread.Sleep
se explican sucintamente aquí :La solución preferida: WaitHandles
El error más cometido es usar
Thread.Sleep
una construcción while ( demostración y respuesta , buena entrada de blog )EDITAR:
Me gustaría mejorar mi respuesta:
fuente
ESCENARIO 1: espere a que finalice la tarea asíncrona: estoy de acuerdo en que WaitHandle / Auto | ManualResetEvent se debe usar en un escenario en el que un subproceso está esperando que se complete la tarea en otro subproceso.
ESCENARIO 2: sincronización mientras que el bucle: Sin embargo, como un mecanismo de sincronización cruda (mientras que + Thread.Sleep) está perfectamente bien para el 99% de las aplicaciones que NO requiere saber exactamente cuándo el hilo bloqueado debería "despertarse *. El argumento que toma 200k ciclos para crear el subproceso también no es válido: el subproceso de bucle de sincronización debe crearse de todos modos y 200k ciclos es solo otro gran número (¿dime cuántos ciclos para abrir un archivo / socket / db llama?).
Entonces, si while + Thread.Sleep funciona, ¿por qué complicar las cosas? ¡Solo los abogados de sintaxis serían prácticos !
fuente
Me gustaría responder a esta pregunta desde una perspectiva de política de codificación, que puede o no ser útil para nadie. Pero particularmente cuando se trata de herramientas destinadas a programadores corporativos de 9 a 5 años, las personas que escriben documentación tienden a usar palabras como "no debería" y "nunca" como "no hagas esto a menos que realmente sepas lo que estás haciendo y por qué ".
Algunos de mis otros favoritos en el mundo de C # son que le dicen que "nunca llame a lock (this)" o "nunca llame a GC.Collect ()". Estos dos se declaran enérgicamente en muchos blogs y documentación oficial, y la OMI son información completa. En cierto nivel, esta información errónea cumple su propósito, ya que mantiene a los principiantes lejos de hacer cosas que no entienden antes de investigar completamente las alternativas, pero al mismo tiempo, dificulta encontrar información REAL a través de motores de búsqueda que parece apuntar a artículos que le dicen que no haga algo sin ofrecer respuesta a la pregunta "¿por qué no?"
Políticamente, se reduce a lo que la gente considera "buen diseño" o "mal diseño". La documentación oficial no debe dictar el diseño de mi aplicación. Si realmente hay una razón técnica por la que no debería llamar a sleep (), entonces la documentación de la OMI debe indicar que está totalmente bien llamarlo bajo escenarios específicos, pero tal vez ofrecer algunas soluciones alternativas que sean independientes del escenario o más apropiadas para el otro escenarios
Claramente, llamar a "dormir ()" es útil en muchas situaciones cuando los plazos están claramente definidos en términos del tiempo real, sin embargo, hay sistemas más sofisticados para esperar y señalar hilos que deben considerarse y entenderse antes de comenzar a tirar sueño ( ) en su código, y arrojar declaraciones innecesarias sleep () en su código generalmente se considera una táctica para principiantes.
fuente
Es el bucle 1) .spinning y 2) .polling de sus ejemplos que la gente advierte contra , no la parte Thread.Sleep (). Creo que Thread.Sleep () generalmente se agrega para mejorar fácilmente el código que está girando o en un bucle de sondeo, por lo que solo está asociado con el código "incorrecto".
Además, las personas hacen cosas como:
donde no se accede a la variable inWait de manera segura para subprocesos, lo que también causa problemas.
Lo que los programadores quieren ver son los subprocesos controlados por eventos y construcciones de señalización y bloqueo, y cuando lo haga, no necesitará Thread.Sleep (), y las preocupaciones sobre el acceso variable seguro para subprocesos también se eliminan. Como ejemplo, ¿podría crear un controlador de eventos asociado con la clase FileSystemWatcher y usar un evento para activar su segundo ejemplo en lugar de bucle?
Como Andreas N. mencionó, leer Threading en C #, por Joe Albahari , es realmente muy bueno.
fuente
Thread.Sleep()
con otra función y llamar a eso en el ciclo while?El modo de suspensión se usa en los casos en que los programas independientes sobre los que no tiene control a veces pueden usar un recurso de uso común (por ejemplo, un archivo), al que su programa necesita acceder cuando se ejecuta, y cuando estos usan el recurso otros programas que su programa no puede usar. En este caso, cuando accede al recurso en su código, coloca su acceso al recurso en un try-catch (para detectar la excepción cuando no puede acceder al recurso), y lo coloca en un ciclo while. Si el recurso es gratuito, el sueño nunca se llama. Pero si el recurso está bloqueado, duerme durante un período de tiempo apropiado e intenta acceder al recurso nuevamente (por eso está haciendo un bucle). Sin embargo, tenga en cuenta que debe poner algún tipo de limitador en el bucle, por lo que no es un bucle potencialmente infinito.
fuente
Tengo un caso de uso que no veo cubierto aquí, y argumentaré que esta es una razón válida para usar Thread.Sleep ():
En una aplicación de consola que ejecuta trabajos de limpieza, necesito hacer una gran cantidad de llamadas a bases de datos bastante caras, a una base de datos compartida por miles de usuarios concurrentes. Para no dañar el DB y excluir a otros durante horas, necesitaré una pausa entre llamadas, del orden de 100 ms. Esto no está relacionado con el tiempo, solo con el acceso a la base de datos para otros subprocesos.
Gastar 2000-8000 ciclos en el cambio de contexto entre llamadas que pueden tardar 500 ms en ejecutarse es benigno, al igual que tener 1 MB de pila para el hilo, que se ejecuta como una sola instancia en un servidor.
fuente
Thread.Sleep
una aplicación de consola de un solo hilo y un solo propósito como la que usted describe está perfectamente bien.Estoy de acuerdo con muchos aquí, pero también creo que depende.
Recientemente hice este código:
Era una simple función animada, y solía
Thread.Sleep
.Mi conclusión, si hace el trabajo, úsalo.
fuente
Para aquellos de ustedes que no han visto un argumento válido contra el uso de Thread.Sleep en SCENARIO 2, realmente hay uno: la salida de la aplicación se mantiene por el ciclo while (SCENARIO 1/3 es simplemente estúpido, así que no merece más mencionando)
Muchos de los que fingen estar al tanto, gritando Thread.Sleep is evil no mencionaron una sola razón válida para aquellos de nosotros que exigimos una razón práctica para no usarla, pero aquí está, gracias a Pete - Thread.Sleep es malvado (se puede evitar fácilmente con un temporizador / controlador)
fuente
Thread.Sleep
no es la razón de esto (el nuevo hilo y el continuo while-loop es)! puede eliminar la líneaThread.Sleep
- et voila: el programa no se cerrará también ...