Tengo un servicio escrito en C # (.NET 1.1) y quiero que realice algunas acciones de limpieza a medianoche todas las noches. Tengo que mantener todo el código contenido dentro del servicio, entonces, ¿cuál es la forma más fácil de lograr esto? ¿Uso Thread.Sleep()
y comprobación del tiempo de renovación?
c#
windows-services
scheduling
scheduled-tasks
ctrlalt3nd
fuente
fuente
Respuestas:
No usaría Thread.Sleep (). Utilice una tarea programada (como han mencionado otros) o configure un temporizador dentro de su servicio, que se activa periódicamente (cada 10 minutos, por ejemplo) y verifique si la fecha cambió desde la última ejecución:
private Timer _timer; private DateTime _lastRun = DateTime.Now.AddDays(-1); protected override void OnStart(string[] args) { _timer = new Timer(10 * 60 * 1000); // every 10 minutes _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); _timer.Start(); //... } private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // ignore the time, just compare the date if (_lastRun.Date < DateTime.Now.Date) { // stop the timer while we are running the cleanup task _timer.Stop(); // // do cleanup stuff // _lastRun = DateTime.Now; _timer.Start(); } }
fuente
Consulte Quartz.NET . Puede usarlo dentro de un servicio de Windows. Le permite ejecutar un trabajo según un programa configurado, e incluso admite una sintaxis simple de "trabajo cron". He tenido mucho éxito con eso.
Aquí hay un ejemplo rápido de su uso:
// Instantiate the Quartz.NET scheduler var schedulerFactory = new StdSchedulerFactory(); var scheduler = schedulerFactory.GetScheduler(); // Instantiate the JobDetail object passing in the type of your // custom job class. Your class merely needs to implement a simple // interface with a single method called "Execute". var job = new JobDetail("job1", "group1", typeof(MyJobClass)); // Instantiate a trigger using the basic cron syntax. // This tells it to run at 1AM every Monday - Friday. var trigger = new CronTrigger( "trigger1", "group1", "job1", "group1", "0 0 1 ? * MON-FRI"); // Add the job to the scheduler scheduler.AddJob(job, true); scheduler.ScheduleJob(trigger);
fuente
¿Una tarea diaria? Parece que debería ser una tarea programada (panel de control), no es necesario un servicio aquí.
fuente
¿Tiene que ser un servicio real? ¿Puedes usar las tareas programadas integradas en el panel de control de Windows?
fuente
La forma en que logro esto es con un temporizador.
Ejecute un temporizador de servidor, haga que compruebe la hora / minuto cada 60 segundos.
Si es la hora / minuto correcta, ejecute su proceso.
De hecho, tengo esto resumido en una clase base que llamo OnceADayRunner.
Déjame limpiar un poco el código y lo publicaré aquí.
private void OnceADayRunnerTimer_Elapsed(object sender, ElapsedEventArgs e) { using (NDC.Push(GetType().Name)) { try { log.DebugFormat("Checking if it's time to process at: {0}", e.SignalTime); log.DebugFormat("IsTestMode: {0}", IsTestMode); if ((e.SignalTime.Minute == MinuteToCheck && e.SignalTime.Hour == HourToCheck) || IsTestMode) { log.InfoFormat("Processing at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute); OnceADayTimer.Enabled = false; OnceADayMethod(); OnceADayTimer.Enabled = true; IsTestMode = false; } else { log.DebugFormat("Not correct time at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute); } } catch (Exception ex) { OnceADayTimer.Enabled = true; log.Error(ex.ToString()); } OnceADayTimer.Start(); } }
La carne de res del método está en la verificación e.SignalTime.Minute / Hour.
Hay ganchos allí para probar, etc. pero así es como podría verse su temporizador transcurrido para que todo funcione.
fuente
Como ya escribieron otros, un temporizador es la mejor opción en el escenario que describió.
Dependiendo de sus requisitos exactos, es posible que no sea necesario verificar la hora actual cada minuto. Si no necesita realizar la acción exactamente a la medianoche, sino solo una hora después de la medianoche, puede optar por el enfoque de Martin de solo verificar si la fecha ha cambiado.
Si la razón por la que desea realizar su acción a la medianoche es que espera una carga de trabajo baja en su computadora, es mejor que tenga cuidado: los demás suelen hacer la misma suposición y, de repente, tiene 100 acciones de limpieza que comienzan entre las 0:00 y las 0:00. : 01 am
En ese caso, debería considerar comenzar su limpieza en un momento diferente. Normalmente hago esas cosas no a la hora del reloj, sino a las medias horas (la 1.30 es mi preferencia personal)
fuente
Le sugiero que use un temporizador, pero configúrelo para que verifique cada 45 segundos, no cada minuto. De lo contrario, puede encontrarse con situaciones en las que, con una carga pesada, se pierda la verificación de un minuto en particular, porque entre el momento en que se activa el temporizador y el momento en que se ejecuta su código y verifica la hora actual, es posible que haya perdido el minuto objetivo.
fuente
También puede probar TaskSchedulerLibrary aquí http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8
Implementar la clase abstracta
AbstractScheduledTask
y llamar alScheduleUtilityFactory.AddScheduleTaskToBatch
método estáticofuente
Para aquellos que encontraron que las soluciones anteriores no funcionan, es porque puede tener un
this
dentro de su clase, lo que implica un método de extensión que, como dice el mensaje de error, solo tiene sentido en una clase estática no genérica. Tu clase no es estática. Esto no parece ser algo que tenga sentido como método de extensión, ya que actúa en la instancia en cuestión, así que elimine elthis
.fuente
Prueba esto:
public partial class Service : ServiceBase { private Timer timer; public Service() { InitializeComponent(); } protected override void OnStart(string[] args) { SetTimer(); } private void SetTimer() { if (timer == null) { timer = new Timer(); timer.AutoReset = true; timer.Interval = 60000 * Convert.ToDouble(ConfigurationManager.AppSettings["IntervalMinutes"]); timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); timer.Start(); } } private void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e) { //Do some thing logic here } protected override void OnStop() { // disposed all service objects } }
fuente