Ejecutar accion todos los dias a la misma hora en C#

publicado por: Anonymous

estoy trabajando en una aplicación de Consola que debe realizar algunas acciones en horarios determinados del día (aclaro que no es un servicio porque necesito la ejecución de procesos)

El asunto es que debo iniciar una aplicación en un momento determinado y cerrarla en otro.

Buscando, encontre una respuesta en S.O en Inglés que hace algo similar a lo que busco pero con una única ejecución, intenté modificar un poco el snippet de la siguiente manera:

    private void SetUpTimer(TimeSpan alertTime, DateTime current, Action<TimeSpan> delg)
    {            

        TimeSpan timeToGo = alertTime - current.TimeOfDay;

        if (timeToGo < TimeSpan.Zero)
        { 
            return;//time already passed
        }
        this.timer = new System.Threading.Timer(x =>
        {
            delg(alertTime);
        }, null, timeToGo, Timeout.InfiniteTimeSpan);
    }

    public void OpenProcess(TimeSpan alertTime)
    {
        Console.WriteLine("Ejecutado {0}",DateTime.Now);            
        SetUpTimer(alertTime, DateTime.Now.AddDays(1), OpenProcess);
    }

y luego lo llamo de la siguiente manera

SetUpTimer(new TimeSpan(13, 44, 00), DateTime.Now, OpenProcess);

La primera vuelta la hace de manera correcta, pero la segunda vez, la función OpenProcess() no se ejecuta

¿Dónde esta mi error?

Gracias!

solución

En tu código timeToGo marca el tiempo que falta para que vuelva a ejecutarse tu timer y se define como una resta de un TimeStamp (alertTime) de otro (current.TimeOfDay).

Que ocurre cuando llamas a SetUpTimer(alertTime, DateTime.Now.AddDays(1), OpenProcess); desde el OpenProcess?

Que utilices AddDays es irrelevante, ya que para calcular el tiempo usas TimeOfDay que no tiene en cuenta la fecha, y además lo llamas a la misma hora en la que se supone debe saltar el tick del timer, con lo que en realidad timeToGo da un resultado negativo, y lógicamente no volverá a dispararse al día siguiente.

Yo ya te he dicho en un comentario que es mejor en mi opinión utilizar una tarea programada de windows para estos menesteres, pero te doy una solución si insistes por este camino.

La solución es usar fechas en lugar de TimeStamps para el cálculo del tiempo que falta para volver a disparar el tick del timer, algo asi:

private void SetUpTimer(Datetime alertTime, Action<TimeSpan> delg)
{            

    TimeSpan timeToGo = alertTime - DateTime.Now;
    ...
}

Para llamarlo la primera vez, asi (si es antes de la hora a la que lo programas):

DateTime fechaProxEjecución = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 13, 44, 0);
SetUpTimer(fechaProxEjecución,OpenProcess);

Y OpenProcess quedaría asi:

public void OpenProcess(TimeSpan alertTime)
{
    Console.WriteLine("Ejecutado {0}",DateTime.Now);            
    DateTime fechaProxEjecución = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day+1, 13, 44, 0);
    SetUpTimer(fechaProxEjecución,OpenProcess);
}
Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *