visual studio servicio instalador ejecutar desde crear como agregar c# windows-services multithreading backgroundworker

c# - studio - installutil servicio de windows



Servicio de Windows que se ejecuta periódicamente (13)

Estoy escribiendo un servicio de Windows que una vez iniciado se ejecutará cada X horas. El proceso que completa es bastante intensivo, así que quiero usar un trabajador de fondo. Estoy usando un archivo de configuración para almacenar las horas entre ejecuciones y la última vez que se ejecutó el servicio.

No estoy exactamente seguro de cuál es la mejor manera de hacer esto, es decir, quiero que el servicio esté inactivo utilizando la menor cantidad de recursos posible y, cuando se ejecute, debe ejecutarse en segundo plano, informar de lo que hizo y volver al modo inactivo.

He pensado en utilizar 2 trabajadores de fondo. El primer trabajador sería una variable local privada para el servicio que ejecuta algo como esto:

while (true) { //create new background worker and run Thread.Sleep(Settings.Default.SleepTimeHours * 3600000); }

con un trabajador secundario que se crea cada iteración del bucle y se destruye cuando se completa. Para admitir la cancelación, creo que tendría que tener una instancia local del segundo trabajador disponible en el servicio, pero será nula si el proceso actualmente no se está ejecutando. Cuando el trabajador secundario finalice, enviará mis informes, establecerá el último tiempo de ejecución en el archivo de configuración y luego eliminará al trabajador y establecerá la referencia en nulo.

Me pregunto si hay una mejor manera de hacer esto o una mejor práctica.

Gracias


¿Qué tal algo más como esto?

public class LongRunningService : ServiceBase { System.Threading.Thread processThread; System.Timers.Timer timer; private Boolean Cancel; protected override void OnStart(string[] args) { timer = new Timer(Settings.Default.SleepTimeHours * 3600000); timer.Elapsed += new ElapsedEventHandler(timer_Tick); timer.Start(); Cancel = false; } protected override void OnContinue() { timer.Start(); } protected override void OnPause() { timer.Stop(); } protected override void OnStop() { if (processThread.ThreadState == System.Threading.ThreadState.Running) { Cancel = true; // Give thread a chance to stop processThread.Join(500); processThread.Abort(); } } void timer_Tick(object sender, EventArgs e) { processThread = new System.Threading.Thread(new ThreadStart(DoWork)); processThread.Start(); } private void DoWork() { try { while (!Cancel) { if (Cancel) { return; } // Do General Work System.Threading.Thread.BeginCriticalRegion(); { // Do work that should not be aborted in here. } System.Threading.Thread.EndCriticalRegion(); } } catch (System.Threading.ThreadAbortException tae) { // Clean up correctly to leave program in stable state. } } }


Alguien tenía una pregunta similar sobre el superusuario. Podría instalar una herramienta que supervise los servicios de Windows. Algo como el servicio Hawk lo ayudaría a mantener los servicios iniciados, o le permitiría programar reinicios automáticos (posiblemente durante la noche) para que el servicio funcione sin problemas.


Apliqué una combinación del Temporizador y el subproceso de trabajo, y hasta ahora funciona bien.

Configuro mi temporizador para que marque cada minuto y, si la hora coincide con la hora programada, creo mi cadena de trabajo.

Utilicé esta técnica para hacer algunas tareas domésticas:

if (nowTimeVar.ToShortTimeString().CompareTo(houseKeep.ToShortTimeString()) == 0) { myHouseKeeper = new clsHouseKeep(archiveFolder, lastday, myCounter, myLogger); }




Después de revisar el tutorial, desarrollé el servicio de Windows que se ejecuta periódicamente cada 60 minutos y comenzará el proceso en segundo plano y ejecutará Test.exe.

public partial class Scheduler : ServiceBase { private Timer timer1 = null; public Scheduler() { InitializeComponent(); } // Get the Exe path private string GetPath() { Assembly assembly = Assembly.GetExecutingAssembly(); return Path.Combine(Path.GetDirectoryName(assembly.Location), "Test.exe"); } // you can right your own custom code // Above vista version the process works as Administrator- "runas" and in old OS it will Start process as per Administartor rights public void startprocess() { // System.Diagnostics.Process.Start(GetPath()); System.Diagnostics.Process process = null; System.Diagnostics.ProcessStartInfo processStartInfo; processStartInfo = new System.Diagnostics.ProcessStartInfo(); processStartInfo.FileName = GetPath(); if (System.Environment.OSVersion.Version.Major >= 6) // Windows Vista or higher { processStartInfo.Verb = "runas"; } else { // No need to prompt to run as admin } processStartInfo.Arguments = ""; process = System.Diagnostics.Process.Start(processStartInfo); } // On start method will load when system Start // timer1_tick Event will call every hour after once start the service automatically protected override void OnStart(string[] args) { //System.Diagnostics.Debugger.Launch(); timer1 = new Timer(); this.timer1.Interval = 3600000; //every 60 min this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Tick); timer1.Enabled = true; } // Timer1_tick will Start process every hour private void timer1_Tick(object sender, ElapsedEventArgs e) { //Write code here to do some job depends on your requirement startprocess(); } // Method will stop the service // we have set the method stop service as false. so service will not stop and run every hour protected override void OnStop() { timer1.Enabled = false; }

}


En mi empresa, confiamos en el programador de tareas de Windows para iniciar el servicio, y luego hacemos que el servicio se cierre. Esto asegura que nuestro servicio siempre se ejecute en el momento adecuado y el sistema de programación permitirá informar sobre el éxito / fracaso, etc.


Esta no es una muy buena idea, ya que usted bloquea su hilo durante todo el período de "SleepTimeHours" y ni siquiera podrá detener el servicio mientras tanto.

Puede hacer este servicio para que se duerma durante, por ejemplo, 5 segundos y luego verificar si es hora de volver al trabajo, y si no, dormir otros 5 segundos (eso le dará la capacidad de respuesta necesaria, si necesita detener la Servicio).

O: es posible que sea mejor escribir una aplicación de consola que se pueda programar utilizando la función de "tareas programadas" de Windows para que se ejecute cada x horas. De esa manera, no bloqueará ni utilizará ningún recurso del sistema si su aplicación no está haciendo nada ...

Bagazo


Normalmente uso un temporizador, luego lo detengo cuando el proceso comienza a ejecutarse.

Aquí hay un artículo que explica cómo hacerlo .


Realmente no quieres usar el trabajador de fondo. Los trabajadores de fondo se utilizan cuando tienes algo que va en primer plano (como UI) y también quieres que se haga algo más en el fondo. En su caso, no hay procesamiento en primer plano, todo lo que tiene es un solo trabajo que necesita ejecutar de vez en cuando.

Además, no se moleste con el negocio del sueño, etc. En su lugar, use un marco de programación, como http://quartznet.sourceforge.net/ para activarlo de vez en cuando. De esta manera, cuando se inicie el servicio, se inicializará el programador y no se hará absolutamente nada hasta que el programador se active. Cuando el programador se active, llamará al método de un objeto que le digas que llame cuando lo inicies.

De esta manera, el servicio apenas consumirá cualquier CPU cuando esté inactivo y funcionará a pleno rendimiento cuando sea necesario.


Tuve la misma discusión con colegas hace aproximadamente 1 hora! Fui con la opción while (_isPolling), porque necesitaba que el trabajo se realizara de forma sincronizada. No quería que el mismo trabajo fuera recogido por otro hilo (el enfoque del temporizador), e implementar un bloqueo adicional para que pareciera un desperdicio.


Use un temporizador para hacer esto.


Utilice un enfoque basado en el enfoque System.Threading.WaitHandle.

using System.Threading; private Thread _thread; private ManualResetEvent _shutdownEvent = new ManualResetEvent(false); private ManualResetEvent _scheduleEvent = new ManualResetEvent(false); private System.Timers.Timer _scheduleTimer = new System.Timers.Timer(); protected override void OnStart(string[] args) { // Configure the timer. _scheduleTimer.AutoReset = false; _scheduleTimer.Interval = 120000; // 2 minutes in milliseconds _scheduleTimer.Elapsed += delegate { _scheduleEvent.Set(); } // Create the thread using anonymous method. _thread = new Thread( delegate() { // Create the WaitHandle array. WaitHandler[] handles = new WaitHandle[] { _shutdownEvent, _scheduleEvent }; // Start the timer. _scheduleTimer.Start(); // Wait for one of the events to occur. while (!_shutdownEvent.WaitOne(0)) { switch (WaitHandle.WaitAny(handles)) { case 0: // Shutdown Event break; case 1: // Schedule Event _scheduleTimer.Stop(); _scheduleEvent.Reset(); ThreadPool.QueueUserWorkItem(PerformScheduledWork, null); break; default: _shutdownEvent.Set(); // should never occur } } } ); _thread.IsBackground = true; _thread.Start(); } protected override void OnStop() { // Signal the thread to shutdown. _shutdownEvent.Set(); // Give the thread 3 seconds to terminate. if (!_thread.Join(3000)) { _thread.Abort(); // not perferred, but the service is closing anyway } } private void PerformScheduledWork(object state) { // Perform your work here, but be mindful of the _shutdownEvent in case // the service is shutting down. // // Reschedule the work to be performed. _scheduleTimer.Start(); }