visual studio servicio instalador crear c# windows-services scheduling scheduled-tasks

c# - crear instalador servicio windows visual studio 2017



¿Cómo puedo programar un servicio de Windows C#para realizar una tarea diariamente? (10)

Tengo un servicio escrito en C # (.NET 1.1) y quiero que realice algunas acciones de limpieza a la medianoche todas las noches. Tengo que mantener todo el código incluido en el servicio, entonces, ¿cuál es la forma más fácil de lograr esto? Uso de Thread.Sleep() y verificando el tiempo que pasa?


¿Tiene que ser un servicio real? ¿Puedes usar las tareas programadas integradas en el panel de control de Windows?


Como otros ya escribieron, un temporizador es la mejor opción en el escenario que describiste.

Dependiendo de sus requisitos exactos, puede que no sea necesario verificar la hora actual cada minuto. Si no necesita realizar la acción exactamente a la medianoche, sino solo dentro de una hora después de la medianoche, puede elegir 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 baja carga de trabajo en su computadora, mejor cuídela: a menudo los demás toman la misma suposición y de repente tiene 100 acciones de limpieza comenzando entre 0:00 y 0 : 01 a.m.

En ese caso, debería considerar comenzar su limpieza en otro momento. Normalmente hago esas cosas no a la hora del reloj, sino a la media hora (a las 1.30 am siendo mi preferencia personal)


Echa un vistazo a Quartz.NET . Puede usarlo dentro de un servicio de Windows. Le permite ejecutar un trabajo según un cronograma configurado e incluso admite una sintaxis simple de "cron job". 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);


La forma en que lo logro es con un temporizador.

Ejecute un temporizador de servidor, haga que verifique la hora / minuto cada 60 segundos.

Si es la hora / minuto correcta, ejecuta tu proceso.

De hecho, tengo esto resumido en una clase base que llamo OnceADayRunner.

Déjame limpiar el código un poco 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 del método está en el cheque e.SignalTime.Minute / Hour.

Hay ganchos para realizar pruebas, etc., pero así es como se verá el temporizador transcurrido para que todo funcione.


No usaría Thread.Sleep (). Utilice una tarea programada (como han mencionado otros) o configure un temporizador dentro de su servicio, que se dispara 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(); } }


Para aquellos que encontraron que las soluciones anteriores no funcionan, es porque pueden tener 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 está actuando en la instancia en cuestión, entonces quítelo.


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 } }


Sugeriría que use un temporizador, pero configúrelo para verificar cada 45 segundos, no minutos. De lo contrario, puede encontrarse en situaciones en las que con carga pesada, la comprobación de un minuto en particular se pierde, porque entre el momento en que se dispara el temporizador y el tiempo de ejecución del código y la hora actual, puede haber perdido el minuto objetivo.



Una tarea diaria? Parece que debería ser solo una tarea programada (panel de control): no hay necesidad de un servicio aquí.