visual usar parar como c# .net vb.net multithreading timer

c# - usar - como parar un timer en visual basic



¿Cómo evitar System.Timers.Timer de cola para la ejecución en un grupo de subprocesos? (5)

Como ninguna de las respuestas es segura para subprocesos, permítanme proponer una que sea:

void oneHundredMS_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (setTimerBodyRunning()) { //only proceed to body if it is not already processing; setTimerBodyRunning must be thread-safe // here you do your long running operation setTimerBodyFinished(); } }

Como puede ver, el controlador del temporizador comprueba primero si ya no se está ejecutando y solo avanza hacia el cuerpo si se devuelve falso. Si se devuelve verdadero, el manejador retorna rápidamente y los ticks no hacen cola (que tendrían que haber usado una instrucción de bloqueo simple). Aquí están las definiciones para setTimerBodyRunning y setTimerBodyFinished:

private bool setTimerBodyRunning() { bool retVal = false; lock (timerBodyRunning) { //timerBodyRunning is type object and it holds a bool. //The reason it is object and not bool is so it can be locked on to ensure thread safety if (!((bool)timerBodyRunning)) { timerBodyRunning = true; retVal = true; } } return retVal; } private void setTimerBodyFinished() { lock (timerBodyRunning) { timerBodyRunning = false; } }

Así es como se inicializaría e iniciaría el temporizador:

object timerBodyRunning = new object(); timerBodyRunning = false; System.Timers.Timer timerFrequency100MS = new System.Timers.Timer(); timerFrequency100MS.Interval = FREQUENCY_MS; //it will fire every 100 milliseconds timerFrequency100MS.Elapsed += new System.Timers.ElapsedEventHandler(oneHundredMS_Elapsed); timerFrequency100MS.Start();

Hay un problema con el comportamiento del temporizador System.Timers estándar. El temporizador aumenta el evento transcurrido con algún intervalo. Pero cuando el tiempo de ejecución dentro del controlador de eventos transcurrido excede el intervalo del temporizador, el grupo de subprocesos comienza el manejo de eventos en cola. Este es un problema en mi caso. Esto se debe a que con mi controlador de eventos Elapsed obtengo algunos datos de la base de datos y hago algo con ellos y finalmente guardo los resultados en la base de datos. Pero el manejo de datos debe proporcionarse solo una vez. Entonces, ¿hay alguna manera de evitar los eventos de cola de espera para System.Timers.Timer?

Como ilustración de este problema, puede considerar el próximo programa de prueba:

public class EntryPoint { private static void TimeProc(object state, ElapsedEventArgs e) { Console.WriteLine("Current time {0} on the thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(20000); } static void Main(string[] args) { Console.WriteLine("Press <Enter> for finishing/n/n"); ThreadPool.SetMaxThreads(10, 10); System.Timers.Timer MyTimer = new System.Timers.Timer(1000); MyTimer.Elapsed += new ElapsedEventHandler(TimeProc); MyTimer.Start(); Console.ReadLine(); MyTimer.Stop(); } }

Y la posible salida será como aquí:

Current time 03.02.2011 0:00:09 on the thread 4 Current time 03.02.2011 0:00:10 on the thread 5 Current time 03.02.2011 0:00:12 on the thread 6 Current time 03.02.2011 0:00:13 on the thread 7 Current time 03.02.2011 0:00:14 on the thread 8 Current time 03.02.2011 0:00:15 on the thread 9 Current time 03.02.2011 0:00:16 on the thread 10 Current time 03.02.2011 0:00:17 on the thread 11 Current time 03.02.2011 0:00:18 on the thread 12 Current time 03.02.2011 0:00:19 on the thread 13 Current time 03.02.2011 0:00:30 on the thread 4 Current time 03.02.2011 0:00:30 on the thread 5

Soluciones posibles:

1) Fue inspirado por: C # Timer vs Thread in Service

Y tiene un código como el aquí referido a la muestra mencionada anteriormente:

public class EntryPoint { private static System.Timers.Timer MyTimer; private static void TimeProc(object state, ElapsedEventArgs e) { Console.WriteLine("Current time {0} on the thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(20000); MyTimer.Enabled = true; } static void Main(string[] args) { Console.WriteLine("Press <Enter> for finishing/n/n"); ThreadPool.SetMaxThreads(10, 10); MyTimer = new System.Timers.Timer(1000); MyTimer.AutoReset = false; MyTimer.Elapsed += new ElapsedEventHandler(TimeProc); MyTimer.Enabled = true; Console.ReadLine(); } }

2) La segunda forma es acerca de SynchronizingObject, pero es valiosa solo para la aplicación de formularios de Windows o para el desarrollo adicional requerido de código para implementar objetos que implementarían la interfaz ISynchronizeInvoke. Más sobre esta forma puedes encontrar aquí

Por lo tanto, por ahora preferiré la primera solución.



Lo que suelo hacer en este caso es detener el temporizador al inicio del controlador de Elapsed y volver a iniciarlo al final. De esta manera, solo está manejando un tic a la vez.

ACTUALIZAR:

Según el enlace de MSDN, creo que lo que quieren decir es que puede establecer su propia bandera (pero aún así tener los ticks incorporados), pero también se deben tomar medidas de seguridad de hilos.


Solo creo una variable de indicador estático. De esta forma, mi temporizador sigue funcionando, pero el código simplemente se pasa por alto si el método no se ha completado antes del siguiente ciclo de temporizador.

En el método utilizado para el temporizador, prueba si un evento está en progreso.

Timer_Method_Called() { if (eventInProgress == 0) { // flag event as in progress eventInProcess == 1; // perform code.... // after code is complete, allow the method to execute eventInProgress == 0; } }


Yo diría simplemente detenerlo y luego iniciarlo después de su larga ejecución como esta.

tmr.Stop(); //Your lengthy execution code goes here tmr.Start();