tick - timer event c#
C#Timer o Thread.Sleep (11)
Estoy ejecutando un servicio de Windows y utilizando un bucle y Thread.Sleep para repetir una tarea, ¿sería mejor utilizar un método de temporizador?
Si es así, un ejemplo de código sería genial
Actualmente estoy usando este código para repetir
int curMinute;
int lastMinute = DateTime.Now.AddMinutes(-1).Minute;
while (condition)
{
curMinute = DateTime.Now.Minute;
if (lastMinute < curMinute) {
// do your once-per-minute code here
lastMinute = curMinute;
}
Thread.Sleep(50000); // sleeps for 50 seconds
if (error condition that would break you out of this) {
break; // leaves looping structure
}
}
Es importante comprender que su código dormirá durante 50 segundos entre finalizar un ciclo y comenzar el siguiente ...
Un temporizador llamará a su bucle cada 50 segundos, que no es exactamente lo mismo.
Ambos son válidos, pero es probable que lo que estás buscando sea un temporizador.
Sí, usar un temporizador liberará un hilo que actualmente está pasando la mayor parte del tiempo durmiendo. Un Temporizador también disparará con mayor precisión cada minuto, por lo que probablemente ya no necesite seguir la pista de lastMinute
.
También estoy de acuerdo, usar un temporizador es la mejor opción. Intenté una solución similar a la tuya en el pasado y comencé a tener problemas en los que el ciclo fallaría, y tendría que esperar otro Thread.Sleep () antes de que volviera a disparar. Además, causó todo tipo de problemas al detener el servicio, recibía errores constantes sobre cómo no respondía y tenía que cerrarse.
El código de @ Prashanth debería ser exactamente lo que necesita.
Tenga en cuenta que al llamar a Sleep () se congelará el servicio, por lo que si se solicita que el servicio se detenga, no reaccionará mientras dure la llamada Sleep ().
Un temporizador es una mejor idea, IMO. De esta forma, si se le pide a su servicio que se detenga, puede responder a eso muy rápidamente, y simplemente no volver a llamar al controlador de tictac del temporizador ... si está durmiendo, el administrador del servicio tendrá que esperar 50 segundos o matar a su hilo, ninguno de los cuales es terriblemente agradable.
class Program
{
static void Main(string[] args)
{
Timer timer = new Timer(new TimerCallback(TimeCallBack),null,1000,50000);
Console.Read();
timer.Dispose();
}
public static void TimeCallBack(object o)
{
curMinute = DateTime.Now.Minute;
if (lastMinute < curMinute) {
// do your once-per-minute code here
lastMinute = curMinute;
}
}
El código podría parecerse a algo como el de arriba
He usado ambos temporizadores y Thread.Sleep (x), o cualquiera, dependiendo de la situación.
Si tengo un código corto que necesita ejecutarse repetidamente, probablemente use un temporizador.
Si tengo un fragmento de código que podría tardar más en ejecutarse que el temporizador de retardo (como recuperar archivos de un servidor remoto a través de FTP, donde no controlo o conozco la demora de la red o el tamaño / conteo de archivos), esperaré por un período fijo de tiempo entre ciclos.
Ambos son válidos, pero como se señaló anteriormente, hacen cosas diferentes. El temporizador ejecuta su código cada x milisegundos, incluso si la instancia anterior no ha finalizado. The Thread.Sleep (x) espera durante un período de tiempo después de completar cada iteración, por lo que la demora total por ciclo siempre será más larga (quizás no mucho) que el período de reposo.
Tendría que decir que dormir es una mejor implementación con una máquina de estado detrás. Esto aún te mantendrá en control de la aplicación en todo momento, pero permitiendo cualquier respuesta necesaria en cualquier momento específico. Esto también manejará las devoluciones de llamada del temporizador que son más cortas que el "Tiempo de ejecución de procesamiento en el ciclo"
Por ejemplo..
<!-- language: c# -->
public enum State
{
Idle = 0,
Processing = 1,
Stop = 100,
}
public void Run()
{
State state = State.Idle; // could be a member variable, so a service could stop this too
double intervalInSeconds = 60;
System.DateTime nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
while (state != State.Stop)
{
switch (state)
{
case State.Idle:
{
if (nextExecution > System.DateTime.Now)
{
state = State.Processing;
}
}
break;
case State.Processing:
{
// do your once-per-minute code here
// if you want it to stop, just set it state to stop.
// if this was a service, you could stop execution by setting state to stop, also
// only time it would not stop is if it was waiting for the process to finish, which you can handle in other ways
state = State.Idle;
nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
}
break;
default:
break;
}
System.Threading.Thread.Sleep(1);
}
}
No estoy respondiendo la pregunta, pero en lugar de tener
if (error condition that would break you out of this) {
break; // leaves looping structure
}
Probablemente deberías tener
while(!error condition)
Además, iría con un Timer
.
Puedes usar cualquiera de los dos. Pero creo que Sleep()
es fácil, claro y más corto de implementar.
Necesitaba un hilo para disparar una vez por minuto ( vea la pregunta aquí ) y ahora he usado un DispatchTimer
basado en las respuestas que recibí.
Las respuestas proporcionan algunas referencias que pueden serle útiles.