visual parar como .net service windows-services timer

.net - parar - Windows Service System.Timers.Timer no se dispara



como parar un timer en visual basic (6)

Al parecer, System.Timers.Timer esconde cualquier excepción, las traga en silencio y luego se ahoga. Por supuesto, puede manejar estos en su método que haya agregado como controlador a su temporizador, pero si la excepción se lanza inmediatamente en la entrada (antes de que se ejecute la primera línea de código, lo que puede suceder si su método declara una variable que utiliza un objeto en una DLL con nombre seguro de la cual tiene la versión incorrecta, por ejemplo, nunca verá esa excepción.

Y nos unirás a todos para arrancarte el pelo.

O podrías hacer esto:

  • cree un método de envoltura que (en un bucle try-catch) llame al método que le gustaría ejecutar. Si este método te está muriendo, el método envuelto puede hacer el manejo de excepciones, sin matar el temporizador, porque si no lo detienes, nunca notará que algo salió mal.

(Terminé deteniendo el temporizador, porque si falla, volver a intentarlo no tiene sentido para esta aplicación en particular ...)

Espero que esto ayude a aquellos que llegaron aquí desde Google (como yo).

Tengo un servicio de Windows escrito en C # que está destinado a realizar una tarea cada pocos minutos. Estoy usando un System.Timers.Timer para esto, pero parece que nunca se dispara. He visto muchas publicaciones diferentes aquí en SO y en otros lugares y no veo qué es lo que está mal con mi código.

Aquí está mi código, con elementos no relacionados con el temporizador eliminados para mayor claridad ...

namespace NovaNotificationService { public partial class NovaNotificationService : ServiceBase { private System.Timers.Timer IntervalTimer; public NovaNotificationService() { InitializeComponent(); IntervalTimer = new System.Timers.Timer(60000); // Default in case app.config is silent. IntervalTimer.Enabled = false; IntervalTimer.Elapsed += new ElapsedEventHandler(this.IntervalTimer_Elapsed); } protected override void OnStart(string[] args) { // Set up the timer... IntervalTimer.Enabled = false; IntervalTimer.Interval = Properties.Settings.Default.PollingFreqInSec * 1000; // Start the timer and wait for the next work to be released... IntervalTimer.Start(); } protected override void OnStop() { IntervalTimer.Enabled = false; } private void IntervalTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // Do the thing that needs doing every few minutes... DoWork(); } } }

Realmente estoy rascándome la cabeza con esto. ¿Alguien puede ver qué tontería me estoy equivocando?

EDITAR: Por sugerencia, agregué IntervalTimer.Enabled = true; antes de IntervalTimer.Start(); En el servicio del método OnStart. Esto no resuelve el problema.

He agregado el registro de rastreo de archivos en el servicio para confirmar algunos de los aspectos internos y estoy seguro de que el valor de Timer.Enabled es verdadero en el momento en que finaliza OnStart ().


Olvidaste activar el temporizador configurando:

IntervalTimer.Enabled = true;

o llamando al método de Start :

IntervalTimer.Start();

protected override void OnStart(string[] args) { // Set up the timer... IntervalTimer.Interval = Properties.Settings.Default.PollingFreqInSec * 1000; // Start the timer and wait for the next work to be released... IntervalTimer.Start(); }


Para agregar a lo que escribió "user1820848", porque ese también era mi problema, si el evento System.timers.timer transcurrido no parece estar activando, coloque todo en el controlador de eventos en un bloque try / catch, y busque Cualquier problema allí. Probé todos los métodos recomendados para tratar este problema (o pensé que tenía), incluido el cambio de system.timers.timer a system.threading.timer, y eso tampoco funcionó.

Creo que el problema se agrava porque muchos de nosotros estamos trasladando nuestras aplicaciones desde nuestra estación de trabajo, donde podemos adjuntar al servicio en ejecución y verificar que funcione, a un servidor donde no tenemos ningún soporte de depuración. Así que te quedas atascado con los mensajes de registro de eventos o los mensajes de seguimiento de rastreo, y es completamente extraño que el evento no se dispare.

Tuve una situación en la que tengo tres servicios en ejecución en este servidor, ejecutando esencialmente el mismo código de temporizador. Incluso fui línea por línea con otro código de servicio en ejecución para asegurarme de que estaba haciendo lo mismo con system.timers.timer. Pero el otro servicio funciona bien, y este no parecía estar disparando el evento en absoluto.

El problema, según resultó, fue que en mis primeras instrucciones débiles estaba activando una clase que intentaba conectarse a Oracle. La llamada estaba fallando, pero en realidad estaba fallando porque la versión del cliente de Oracle en mi estación de trabajo y servidor era ligeramente diferente. Ocurrió cuando el CLR estaba resolviendo las referencias, por lo que no estaba atrapado en los bloques de prueba / captura de mi clase subyacente. Si estuviera depurando, el depurador habría marcado el error. Al correr en el servidor, el CLR no tenía forma de contarme sobre el problema. Así que mi servicio se quedó allí sentado en un error sin trampa.

Poner todo en un try / catch inmediatamente señaló el problema. Ponga su intento antes de cualquier declaración en esa subrutina. Si está fallando en una declaración muy temprana, así es como la atrapará.

[Perdón por la respuesta por separado, pero ¿tienes que proporcionar respuestas para obtener suficiente reputación como para incluso comentar sobre la respuesta de otra persona?!?]

[Editar: otra cosa que debes intentar es sacar tu código del evento del temporizador, ponerlo en otro sub / función, invocarlo desde tu código de inicio y también poner la llamada a la función en tu evento del temporizador. Semanas más tarde, de vuelta en mi estación de trabajo, tratando de ejecutar el mismo código, y tengo la sensación de que no se está llamando a mi evento de temporizador, y he estado aquí antes. ¡En efecto! Pero poner todo en un try / catch tampoco está funcionando!?! Lo moví a una llamada de función y Bam, ahí está mi excepción: Oracle de nuevo. Pero no surgió incluso con cada línea dentro de un try / catch, hasta que eliminé el código del evento del temporizador y lo intenté de nuevo.]


También tuve que cambiar a System.Threading.Timer. Para facilitar el refabricado y facilitar el trabajo de otros, creé una clase separada, que contiene una instancia de System.Threading.Timer y tiene casi los mismos métodos que System.Timers.Timer, por lo que el código de llamada requiere cambios mínimos:

/// <summary> /// Custom Timer class, that is actually a wrapper over System.Threading.Timer /// </summary> /// <seealso cref="System.IDisposable" /> internal class Timer : IDisposable { System.Threading.Timer _timer; public Timer() { } public Timer(int interval) : this() { this.Interval = interval; } public bool AutoReset { get; set; } public bool Enabled { get; set; } public int Interval { get; set; } public Action<object> OnTimer { get; internal set; } public void Dispose() { if (_timer != null) { _timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); _timer.Dispose(); _timer = null; } } public void Start() { _timer = new System.Threading.Timer( new System.Threading.TimerCallback(OnTimer), null, 0, Interval); } public void Stop() { if (_timer != null) { _timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); } } }

¡Espero que esto sea de ayuda!


Aquí está mi trabajo alrededor ...

Después de demasiadas horas buscando una respuesta a esto, descubrí una amplia variedad de artículos y blogs que analizan los temporizadores en los servicios de Windows. He visto muchas opiniones sobre esto y todas se dividen en tres categorías y en orden descendente de frecuencia:

  1. No use System.Windows.Forms.Timer porque no funcionará. (Esto solo tiene sentido)

  2. No use System.Threading.Timer porque no funciona, use System.Timers.Timer lugar.

  3. No use System.Timers.Timer porque no funciona, use System.Threading.Timer lugar.

Basándome en esto, probé el 2. Este es también el enfoque que parece ser recomendado por Microsoft, ya que dicen que System.Timers.Timer es adecuado para "aplicaciones de servidor" .

Lo que he encontrado es que System.Timers.Timer simplemente no funciona en mi aplicación de servicio de Windows. Por lo tanto, he cambiado a System.Threading.Timer . Es una molestia ya que requiere un poco de refactorización para que funcione.

Esto es aproximadamente como se ve mi código de trabajo ahora ...

namespace NovaNotificationService { public partial class NovaNotificationService : ServiceBase { private System.Threading.Timer IntervalTimer; public NovaNotificationService() { InitializeComponent(); } protected override void OnStart(string[] args) { TimeSpan tsInterval = new TimeSpan(0, 0, Properties.Settings.Default.PollingFreqInSec); IntervalTimer = new System.Threading.Timer( new System.Threading.TimerCallback(IntervalTimer_Elapsed) , null, tsInterval, tsInterval); } protected override void OnStop() { IntervalTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); IntervalTimer.Dispose(); IntervalTimer = null; } private void IntervalTimer_Elapsed(object state) { // Do the thing that needs doing every few minutes... // (Omitted for simplicity is sentinel logic to prevent re-entering // DoWork() if the previous "tick" has for some reason not completed.) DoWork(); } } }

Odio la solución del "Doctor, doctor, me duele cuando hago esto ...", pero a eso debo recurrir. Una opinión más en la pila para el próximo tipo con este problema ...


private void IntervalTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // Do the thing that needs doing every few minutes... DoWork(); //Add following 2 lines. It will work. **IntervalTimer.Interval= 100; //any value IntervalTimer.Start();** }