Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reset System.Timers.Timer to prevent Elapsed event

I am trying to use the Timer to trigger an event to send data across the network. I created a simple class to debug. Basically I have a List<string> I'd like to send. I want the following to happen:

  1. Add string to List
  2. Start Timer for 10 seconds
  3. Add second string to List before Timer.Elapsed
  4. Restart Timer back at 10 seconds.

So far I have this:

public static List<string> list;
public static Timer timer;
public static bool isWiredUp = false;

public static void Log(string value) {
    if (list == null) list = new List<string>();
    list.Add(value);

    //this does not reset the timer, elapsed still happens 10s after #1
    if (timer != null) {
        timer = null;
    }

    timer = new Timer(10000);
    timer.Start();
    timer.Enabled = true;
    timer.AutoReset = false;

    if (!isWiredUp) {
        timer.Elapsed += new ElapsedEventHandler(SendToServer);
        isWiredUp = true;
    }
}

static void SendToServer(object sender, ElapsedEventArgs e) {
    timer.Enabled = false;
    timer.Stop();
}

Any ideas?

like image 860
tedski Avatar asked Feb 13 '13 19:02

tedski


People also ask

How do I stop a timer elapsed event?

It would have already queued before you have called Stop method. It will fire at the elapsed time. To avoid this happening set Timer. AutoReset to false and start the timer back in the elapsed handler if you need one.

What does timer elapsed mean?

Elapsed time is the amount of time that passes from the start of an event to its finish. In simplest terms, elapsed time is how much time goes by from one time (say 3:35pm) to another (6:20pm).

Does system timers timer run in a separate thread?

Yes, they run in a different thread.

How does system timer work?

Remarks. The Timer component is a server-based timer that raises an Elapsed event in your application after the number of milliseconds in the Interval property has elapsed. You can configure the Timer object to raise the event just once or repeatedly using the AutoReset property.


1 Answers

You can use the Stop function followed immediately by the Start function to "restart" the timer. Using that you can create the Timer when the class is first created, wire up the Elapsed event at that time, and then do nothing but call those two methods when an item is added. It will either start, or restart, the timer. Note that calling Stop on a timer that hasn't yet been started just does nothing, it doesn't throw an exception or cause any other problems.

public class Foo
{
    public static List<string> list;
    public static Timer timer;
    static Foo()
    {
        list = new List<string>();
        timer = new Timer(10000);
        timer.Enabled = true;
        timer.AutoReset = false;
        timer.Elapsed += SendToServer;
    }

    public static void Log(string value)
    {
        list.Add(value);
        timer.Stop();
        timer.Start();
    }

    static void SendToServer(object sender, ElapsedEventArgs e)
    {
        //TODO send data to server

        //AutoReset is false, so neither of these are needed
        //timer.Enabled = false;
        //timer.Stop();
    }
}

Note that rather than using a List it's very possible that you want to use a BlockingCollection<string> instead. This has several advantages. First, the Log methods will work if called at the same time from multiple threads; as is multiple concurrent logs could break the list. It also means that SendToServer can be taking items out of the queue at the same time that new items are added. If you use a List you'll need to lock all access to the list (which might not be a problem, but isn't as straightforward).

like image 83
Servy Avatar answered Oct 06 '22 00:10

Servy