Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Threading.Timer with Autoreset or Single Thread?

I want to create a class that reads SMS messages from a GSM device.

I created a timer(system.threading) that reads for incoming message every second.


public void ReadMessage(){
//read sms messages
//and store it into the database
}

Sometimes ReadMessage() takes more than a second. How can I prevent the timer from calling this procedure when the previous one is not yet finished?
1. Are AutoResetEvent and WaitOne good for this?
2. Is Threading.Timer a good choice? or should I do it on a single thread?

like image 998
h3n Avatar asked Feb 23 '23 19:02

h3n


2 Answers

You should use a System.Timers.Timer, which is easier to work with.
(It's a friendlier wrapper around Threading.Timer)

Set AutoReset to false, then Start() the timer again at the end of the handler.

Don't use a dedicated thread; there's no point in keeping a thread around doing nothing so that you can wake it up every second.

like image 135
SLaks Avatar answered Mar 07 '23 16:03

SLaks


Although this question is quite old, you can inspire by this code. It doesn't use any additional thread and it doesn't count time during execution of your code.

/// <summary>
/// Single thread timer class.
/// </summary>
public class SingleThreadTimer: IDisposable
{
    private readonly Timer timer;
    private readonly Action timerAction;

    /// <summary>
    /// Initializes a new instance of the <see cref="SingleThreadTimer"/> class.
    /// </summary>
    /// <param name="interval">The interval time.</param>
    /// <param name="timerAction">The timer action to execute.</param>
    /// <exception cref="System.ArgumentNullException">timerAction</exception>
    /// <exception cref="System.ArgumentException">interval</exception>
    public SingleThreadTimer(double interval, Action timerAction)
    {
        if (timerAction == null)
            throw new ArgumentNullException("timerAction");

        if (interval <= 0)
            throw new ArgumentException(string.Format("Invalid value '{0}' for parameter 'interval'.", interval), "interval");

        this.timerAction = timerAction;

        this.timer = new Timer(interval)
        {
            AutoReset = false
        };

        timer.Elapsed += timer_Elapsed;
        timer.Start();
    }

    public void Dispose()
    {
        if (timer != null)
            timer.Dispose();
    }

    private void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            timerAction();
        }
        finally
        {
            // Enable timer again to continue elapsing event.
            timer.Enabled = true;
        }
    }
}
like image 25
Milan Matějka Avatar answered Mar 07 '23 15:03

Milan Matějka