visual try threading thread studio second one c# multithreading

c# - try - Alternativas a Thread.Sleep()



try sleep c# (11)

Cada N minutos que queremos ejecutar a través de una lista de tareas. Así que creamos un ejecutor de tareas con un

do { DoWork(); }while(!stopRequested)

Ahora queremos tener una pausa entre los ciclos de trabajo. Todo el mundo parece pensar que Thread.Sleep () es el demonio. He visto mencionar el uso de Monitor / Evento, pero no tenemos a alguien más diciéndonos que hagamos el trabajo. Solo queremos hacer cosas cada N minutos como un reloj.

Entonces, ¿hay alguna alternativa o he encontrado un uso válido de Thread.Sleep?

Alguien en otra publicación mencionó WaitHandle.WaitOne () como alternativa, pero aparentemente no se puede llamar a eso desde un método no estático. O al menos no puedo porque obtengo un error de tiempo de compilación de ..

Se requiere una referencia de objeto para el campo, método o propiedad no estático ''System.Threading.WaitHandle.WaitOne (System.TimeSpan)''


Como han dicho otros respondedores, los temporizadores pueden funcionar bien para usted.

Si quieres tu propio hilo, no usaría Thread.Sleep aquí, solo porque si necesitas cerrar la aplicación, no hay una buena manera de decirle que salga de la suspensión. He usado algo así antes.

class IntervalWorker { Thread workerThread; ManualResetEventSlim exitHandle = new ManualResetEventSlim(); public IntervalWorker() { this.workerThread = new Thread(this.WorkerThread); this.workerThread.Priority = ThreadPriority.Lowest; this.workerThread.IsBackground = true; } public void Start() { this.workerThread.Start(); } public void Stop() { this.exitHandle.Set(); this.workerThread.Join(); } private void WorkerThread() { int waitTimeMillis = 10000; // first work 10 seconds after startup. while (!exitHandle.Wait(waitTimeMillis)) { DoWork(); waitTimeMillis = 300000; // subsequent work at five minute intervals. } } }


Encontré una forma de hackear Thread.Sleep haciendo que el programa se active periódicamente y realice eventos si necesita cancelar. Vea abajo:

// Pay attention every 1/10 sec to maintain some UI responsiveness while (val > 0) { Thread.Sleep(100); val = val - 100; Application.DoEvents(); if (val == x) { // You could do some conditional stuff here at specific times } }

Sustituya val con el retraso deseado en milisegundos. Cuanto más Thread.Sleep el valor ms de Thread.Sleep más receptivo parecerá el programa. 100ms me parece aceptable. 50 ms es lo mejor


He usado tanto un temporizador en una aplicación WinForms como una aplicación de consola iniciada periódicamente por un ScheduledTask en un servidor. El WinForms con un temporizador se ha utilizado en los casos en que quiero que aparezca notificaciones que se ejecutó y lo que encontró (he configurado estos para mimetizar a la bandeja del sistema). Para las situaciones en las que solo quiero recibir notificaciones si algo falla en un servidor, las coloco en el servidor como aplicaciones de consola y las ejecuto como tareas programadas. Eso parece funcionar bastante bien.

Creo que traté de usar Sleep en las aplicaciones donde ahora uso Timers, y no me gustó el resultado. Para empezar, con un temporizador puedo llamar la aplicación minimizada muy fácilmente para establecer o cambiar las configuraciones en el frente. Si la aplicación está dormida, tiene dificultades para recuperar el acceso mientras está durmiendo.


Las tres opciones que puedo pensar en la parte superior de mi cabeza son:

pero estoy seguro de que muchos mencionarán: Thread.Sleep() no es tan malo.


Puede usar un ManualResetEvent que establezca cuando sea el momento de detenerse, y luego hacer un WaitOne en él.


Puede usar un temporizador System.Timers.Timer y realizar el trabajo en su controlador de tiempo transcurrido.


Según tengo entendido, Thread.Sleep () es malo porque fuerza a los recursos del subproceso a salir del caché, por lo que deben volver a cargarse después. No es gran cosa, pero podría agravar los problemas de rendimiento en situaciones de mucha carga. Y luego está el hecho de que el tiempo no es preciso, y que efectivamente no puede esperar por duraciones de menos de 10 ms ...

Yo uso este fragmento:

new System.Threading.ManualResetEvent(false).WaitOne(1000);

Fácil como un pastel y todo encaja en una línea. Crea un nuevo controlador de eventos que nunca se establecerá, y luego espera el período de tiempo de espera completo, que usted especifica como el argumento para WaitOne() .

Aunque, para este escenario específico, un temporizador probablemente sería un enfoque más apropiado:

var workTimer = new System.Threading.Timer( (x) => DoWork(), null, 1000, // initial wait period 300000); // subsequent wait period

Luego, en lugar de establecer una variable de cancelación, detendría el temporizador con workTimer.Stop() .

Editar :

Como las personas aún lo encuentran útil, debo agregar que .NET 4.5 introduce el método Task.Delay , que es aún más conciso y también admite asincrónico:

Task.Delay(2000).Wait(); // Wait 2 seconds with blocking await Task.Delay(2000); // Wait 2 seconds without blocking


Si todo lo que estás haciendo es algo así como:

while (!stop_working) { DoWork(); Thread.Sleep(FiveMinutes); }

Entonces sugeriría no usar ningún hilo. En primer lugar, no hay una razón particularmente buena para incurrir en la sobrecarga del sistema de un hilo dedicado que pasa la mayor parte del tiempo durmiendo. En segundo lugar, si configura el indicador stop_working 30 segundos después de que el hilo deje de dormir, tendrá que esperar cuatro minutos y medio antes de que el hilo se active y finalice.

Sugeriría como otros lo han hecho: usar un temporizador:

System.Threading.Timer WorkTimer; // Somewhere in your initialization: WorkTimer = new System.Threading.Timer((state) => { DoWork(); }, null, TimeSpan.FromMinutes(5.0), TimeSpan.FromMinutes(5.0));

Y para cerrar:

WorkTimer.Dispose();


Tienes que llamar a WaitOne en un WaitHandle , sin dudas. Es un método de instancia. De lo contrario, ¿cómo sabría qué esperar?

Definitivamente es mejor tener algo que pueda reaccionar en lugar de dormir, para que pueda notar la cancelación sin esperar minutos sin motivo. Otra alternativa a WaitHandle es usar Monitor.Wait / Pulse .

Sin embargo, si usa .NET 4, analizaré lo que ofrece la Biblioteca paralela de tareas ... está en un nivel ligeramente más alto que las otras opciones, y generalmente es una biblioteca bien pensada.

Para las tareas de trabajo regulares, es posible que desee ver el uso de un Timer (ya sea System.Threading.Timer o System.Timers.Timer ) o posiblemente incluso Quartz.NET .


Yo usaría un temporizador de espera que señala un AutoResetEvent. Su hilo debe esperar a este objeto WaitHandle. Aquí hay una pequeña aplicación de consola que muestra este enfoque:

class Program { const int TimerPeriod = 5; static System.Threading.Timer timer; static AutoResetEvent ev; static void Main(string[] args) { ThreadStart start = new ThreadStart(SomeThreadMethod); Thread thr = new Thread(start); thr.Name = "background"; thr.IsBackground = true; ev = new AutoResetEvent(false); timer = new System.Threading.Timer( Timer_TimerCallback, ev, TimeSpan.FromSeconds(TimerPeriod), TimeSpan.Zero); thr.Start(); Console.WriteLine(string.Format("Timer started at {0}", DateTime.Now)); Console.ReadLine(); } static void Timer_TimerCallback(object state) { AutoResetEvent ev = state as AutoResetEvent; Console.WriteLine(string.Format ("Timer''s callback method is executed at {0}, Thread: ", new object[] { DateTime.Now, Thread.CurrentThread.Name})); ev.Set(); } static void SomeThreadMethod() { WaitHandle.WaitAll(new WaitHandle[] { ev }); Console.WriteLine(string.Format("Thread is running at {0}", DateTime.Now)); } }


Thread.Sleep no es el demonio, podrías usarlo para un escenario como este. No es muy confiable por cortas duraciones.

Usar un WaitHandle es una buena opción, pero necesita una instancia específica de un identificador de espera. No hará esto solo, sin embargo.

Dicho esto, la mayoría de las veces, operaciones como esta son más adecuadas para usar un temporizador. ¿Hay alguna razón por la que intente procesar esto en un bucle en lugar de simplemente usar un temporizador para comenzar el elemento de trabajo?