0

I use System.Timers.Timer to start a timer. There is an event that is raised occasionally, every time this event raises I increment a counter. If the counter > 3, I execute a method to perform an action and I need to repeatedly do this.

I reset the counter every N seconds to start counting the events again from 1. When the counter resets to 0, I need to stop the ongoing action that gets triggered by the timer, but I can't get it to stop and this method keeps on executing even after the counter has reset to 0.

My program has this structure:

class Program
{
        static void Main(string[] args)
        {
            var counter = 0;

            //Create timer
            var delayTimer = new System.Timers.Timer
            {
               // Interval = 900000, // every 15 minutes 
                Interval = 45000, // debug 
                AutoReset = true,
            };

            // Start the timer
            delayTimer.Start();


        delayTimer.Elapsed += ((o, e) =>
                {
                    // when timer elapses reset the counter
                    counter = 0;
                    // stop the timed action function which was executing every N seconds for counter > 3
                    TimedTask(1, false, "stop"); // stop the timer
                });


        // an event raises the counter

            while (event)
            {

                counter++;  // keeps track of events raised

                if (counter > 3)
                {
                    // take a specific action
                    TimedTask(30000, true); // start the timer to perform an action every 30 seconds
                }

            }

            // to keep the application going
            System.Windows.Forms.Application.Run();

        }

    }

    // method to start a timer for repeating a task every N seconds, or stop the counter for this ongoing timed task
    public static void TimedTask(int interval, bool autoreset, string stop = null)
        {  
            //Create timer
            var delayTimer = new System.Timers.Timer
            {
                Interval = interval, // every N seconds
                AutoReset = autoreset, // true: repeat, false: don't repeat
            };


            if (stop != null)
            {

                delayTimer.Elapsed += ((o, e) =>
                {
                    // if 'stop' passed as string, stop executing the task every N seconds
                    delayTimer.Stop(); 
                });


            }
            else
            {
                // Start the timer
                delayTimer.Start();

                // Create the event handler
                delayTimer.Elapsed += ((o, e) =>
                {
                    // when timer elapses call the method below
                    RepeatedAction();
                });
            }

        }

    // repeated action method
    public static void RepeatedAction()
    {

        // perform an action, repeat it every N seconds

    }



}

I have tried sending an additional string parameter "stop" to un-register the timer but this does not work.

I am creating two different timers: one for resetting the counter and one for repeating the timed task, could I minimise this by creating a timer method or something? Thanks in advance.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
mrT
  • 86
  • 3
  • 9
  • Have you tried using a CancellationToken? – Igor Meszaros Jan 11 '19 at 12:05
  • Possible duplicate of [Is there a Task based replacement for System.Threading.Timer?](https://stackoverflow.com/questions/4890915/is-there-a-task-based-replacement-for-system-threading-timer) – Murray Foxcroft Jan 11 '19 at 12:10
  • The event handler of the `Timer` will be called on a background (thread pool) thread. If you want to abort that event handler's execution, you have two options: 1) obtain a thread's reference and call `Thread.Abort` - **don't do this**, it's nasty; and 2) in your event handler (`RepeatedAction`), check for some flag to abort the method execution. – dymanoid Jan 11 '19 at 12:10
  • @dymanoid, thank you, your suggestion (2) seems very feasible. What sort of flag can I set in my RepeatedAction(), do I to send some additional data through the event handler? – mrT Jan 11 '19 at 14:25
  • I'd suggest a simple Boolean flag. Something like `if (stopAction) return;` – dymanoid Jan 11 '19 at 14:39
  • @dymanoid, how can I raise this flag from another method? I am not able to send a string notifier to `RepeatedAction()`. – mrT Jan 11 '19 at 15:10
  • Use a static field, an instance field, or a closure over a lambda. – dymanoid Jan 11 '19 at 15:27

0 Answers0