¿Cómo llamar a un método diariamente, en un momento específico, en C#?

Resuelto Delta76 asked hace 14 años • 19 respuestas

Busqué en SO y encontré respuestas sobre Quartz.net. Pero parece ser demasiado grande para mi proyecto. Quiero una solución equivalente, pero más simple y (en el mejor de los casos) integrada en el código (no se requiere una biblioteca externa). ¿Cómo puedo llamar a un método diariamente, a una hora específica?

Necesito agregar alguna información sobre esto:

  • La forma más sencilla (y fea) de hacer esto es comprobar la hora cada segundo/minuto y llamar al método en el momento adecuado.

Quiero una forma más eficaz de hacer esto, sin necesidad de comprobar la hora constantemente y tengo control sobre si el trabajo está terminado o no. Si el método falla (debido a algún problema), el programa debería saber escribir para registrar/enviar un correo electrónico. Por eso necesito llamar a un método, no programar un trabajo.

Encontré esta solución Llame a un método a una hora fija en Java en Java. ¿Existe una forma similar en C#?

EDITAR: He hecho esto. Agregué un parámetro a void Main() y creé un bat (programado por el Programador de tareas de Windows) para ejecutar el programa con este parámetro. El programa se ejecuta, hace el trabajo y luego sale. Si un trabajo falla, es capaz de escribir registros y enviar correos electrónicos. Este enfoque se ajusta bien a mis necesidades :)

Delta76 avatar Jul 14 '10 11:07 Delta76
Aceptado
  • Crea una aplicación de consola que haga lo que estás buscando
  • Utilice la funcionalidad " Tareas programadas " de Windows para ejecutar esa aplicación de consola en el momento en que la necesite.

¡Eso es realmente todo lo que necesitas!

Actualización: si quieres hacer esto dentro de tu aplicación, tienes varias opciones:

  • en una aplicación de Windows Forms , puede acceder al Application.Idleevento y verificar si ha llegado la hora del día para llamar a su método. Este método solo se llama cuando tu aplicación no está ocupada con otras cosas. Creo que una comprobación rápida para ver si se ha alcanzado el tiempo objetivo no debería estresar demasiado la aplicación...
  • en una aplicación web ASP.NET, existen métodos para "simular" el envío de eventos programados; consulte este artículo de CodeProject
  • y, por supuesto, también puede simplemente "hacerlo usted mismo" en cualquier aplicación .NET; consulte este artículo de CodeProject para ver una implementación de muestra.

Actualización n.° 2 : si desea verificar cada 60 minutos, puede crear un temporizador que se active cada 60 minutos y, si se acaba el tiempo, llama al método.

Algo como esto:

using System.Timers;

const double interval60Minutes = 60 * 60 * 1000; // milliseconds to one hour

Timer checkForTime = new Timer(interval60Minutes);
checkForTime.Elapsed += new ElapsedEventHandler(checkForTime_Elapsed);
checkForTime.Enabled = true;

y luego en su controlador de eventos:

void checkForTime_Elapsed(object sender, ElapsedEventArgs e)
{
    if (timeIsReady())
    {
       SendEmail();
    }
}
marc_s avatar Jul 14 '2010 04:07 marc_s

Creé un programador simple que es fácil de usar y no es necesario usar una biblioteca externa. TaskScheduler es un singleton que mantiene referencias en los temporizadores para que los temporizadores no se recopilen como basura y pueda programar múltiples tareas. Puede configurar la primera ejecución (hora y minuto), si al momento de programar este tiempo ya pasó, programar el inicio al día siguiente a esa hora. Pero es fácil personalizar el código.

Programar una nueva tarea es muy sencillo. Ejemplo: A las 11:52 la primera tarea es cada 15 segundos, el segundo ejemplo es cada 5 segundos. Para la ejecución diaria, establezca 24 en el parámetro 3.

TaskScheduler.Instance.ScheduleTask(11, 52, 0.00417, 
    () => 
    {
        Debug.WriteLine("task1: " + DateTime.Now);
        //here write the code that you want to schedule
    });

TaskScheduler.Instance.ScheduleTask(11, 52, 0.00139,
    () =>
    {
        Debug.WriteLine("task2: " + DateTime.Now);
        //here write the code that you want to schedule
    });

Mi ventana de depuración:

task2: 07.06.2017 11:52:00
task1: 07.06.2017 11:52:00
task2: 07.06.2017 11:52:05
task2: 07.06.2017 11:52:10
task1: 07.06.2017 11:52:15
task2: 07.06.2017 11:52:15
task2: 07.06.2017 11:52:20
task2: 07.06.2017 11:52:25
...

Simplemente agregue esta clase a su proyecto:

public class TaskScheduler
{
    private static TaskScheduler _instance;
    private List<Timer> timers = new List<Timer>();

    private TaskScheduler() { }

    public static TaskScheduler Instance => _instance ?? (_instance = new TaskScheduler());

    public void ScheduleTask(int hour, int min, double intervalInHour, Action task)
    {
        DateTime now = DateTime.Now;
        DateTime firstRun = new DateTime(now.Year, now.Month, now.Day, hour, min, 0, 0);
        if (now > firstRun)
        {
            firstRun = firstRun.AddDays(1);
        }

        TimeSpan timeToGo = firstRun - now;
        if (timeToGo <= TimeSpan.Zero)
        {
            timeToGo = TimeSpan.Zero;
        }

        var timer = new Timer(x =>
        {
            task.Invoke();
        }, null, timeToGo, TimeSpan.FromHours(intervalInHour));

        timers.Add(timer);
    }
}
dvjanm avatar Jun 07 '2017 10:06 dvjanm

Siempre que creo aplicaciones que requieren dicha funcionalidad, siempre uso el Programador de tareas de Windows a través de una biblioteca .NET simple que encontré.

Consulte mi respuesta a una pregunta similar para obtener un código de muestra y más explicaciones.

Maxim Zaslavsky avatar Jul 14 '2010 06:07 Maxim Zaslavsky