Archivo por meses: mayo 2016

Realizar tareas programadas en una aplicación ASP.Net

Desarrollo y programación .net

Por circunstancias de la vida me he encontrado últimamente con varios proyectos realizados en ASP.Net que requieren realizar tareas programadas que se ejecuten en un momento concreto del día independientemente si existe o no usuarios conectados.

Como suele ocurrir existen muchas maneras de abordar esta funcionalidad:

  • Mediante Servicios Windows, siempre que tengamos total control de nuestro servidor y el entorno para realizar la tarea en cuestión (Base de Datos, acceso al sistema de ficheros, etc.)
  • Mediante WCF. También sería necesario acceso total a IIS y a su configuración.
  • Mediante programación dentro de la misma aplicación ASP.Net.

Seguro que existe alguna otra pero mi objetivo primordial en todos estos proyectos que debía realizar era optimizar los tiempos mantenimiento, para ello creo que la última solución resultaba la mejor en este caso ya que solo tendría que dedicarme a modificar un único proyecto: la aplicación ASP.Net. De otro modo tendría que instalar el servicio windows o configurar el proyecto WCF dentro del IIS.

Así que me puse a investigar por la web cuales eran las mejores prácticas de cómo realizar una tarea programada en background dentro de ASP.Net. Encontré una solución que me parecía muy clara y que muchos reportaban como buena. Su funcionamiento requería del uso de la caché de la aplicación web y el método application_start dentro del global.asax.

Su uso consistía en añadir un objeto a la cache en el contexto de ejecución para que cuando dicha cache expirara utilizara el evento para ejecutar de nuevo la tarea. La palabra clave para este método es CacheItemRemovedCallback… pero os anticipo que yo NO LO UTILIZARÉ MÁS.

No voy a adentrar en los motivos de rehusar finalmente este método pero os puedo asegurar que da problemas, incluso cuando establecemos el tiempo de inactividad a 0 dentro del pool de aplicaciones del IIS, que en principio parecía que podía ser una de las soluciones.

Investigando un poco más pude dar con un componente muy interesante: Quartz.

Su uso es muy sencillo y parece ser que existe un componente homónimo en Java.

Quartz tiene una Interfaz denominada IJob que únicamente expone un método llamado Execute(). Si deseas hacer una tarea a nivel de aplicación únicamente debes llamar JobScheduler.Start() dentro de Application_Start() del Global.asax.

using Quartz;
using Quartz.Impl;
using System;
 
namespace ScheduledTaskExample.ScheduledTasks
{
    public class JobScheduler
    {
        public static void Start()
        {
            IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
            scheduler.Start();
 
            IJobDetail job = JobBuilder.Create<MyJob>().Build();
 
            ITrigger trigger = TriggerBuilder.Create()
                .WithDailyTimeIntervalSchedule
                  (s =>
                     s.WithIntervalInHours(24)
                    .OnEveryDay()
                    .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(0, 0))
                  )
                .Build();
 
            scheduler.ScheduleJob(job, trigger);
        }
    }
}