LeoM
LeoM

Reputation: 31

Can I change a timer's interval without resetting it?

I have a timer that is supposed to generate a Console.Beep at the rate of my Heart Rate in beats/minute. I am using the following simple formula to calculate the Timer.Interval in my C# timer:

    ServerVarValues = new ws ServerVarValues();
    this.timerHeartBeatSound = new System.Windows.Forms.Timer(this.components);

    public class ServerVarValues
    {
        public int HR;
        public DateTime LastHRUpdate;
        public int SpO2;
        public DateTime LastO2Update;
        public double Temperature;
        public DateTime LastTempUpdate;
    }

 //... I plug in my heart rate to calculate my new timer interval...    
int tVal = (int)Math.Round((ws.HR / 60.0) * 1000,0);   
timerHeartBeatSound.Interval = tVal;

 // and with the new interval, the timer generates a Tick Event that runs this
   private void PlayHeartBeatSound(object sender, EventArgs e)
    {
        Console.Beep();   
    }

I am reading my heart rate from a wearable. The problem is that every time that my HR changes, the timer is reset when I change the timer's interval. Thus, I hear hiccups often instead of a smooth changing heart rate sound.

Any ideas on how to avoid resetting the timer every time the heart rate changes?

Upvotes: 1

Views: 3503

Answers (2)

Hans Passant
Hans Passant

Reputation: 942040

Yes, this is by design. When you change the Interval property, and it is not the same, then the Timer resets itself. You cannot alter this behavior.

So what you must do is not update Interval. Not until the next Tick happens. Which is fine, the heart-beats happen quickly enough. You'll need another variable:

public class ServerVarValues {
    public int NextInterval;
    // etc...
}

And initialize it when you start the timer or update the heart-rate value:

...
int tVal = (int)Math.Round((ws.HR / 60.0) * 1000,0); 
if (timerHeartBeatSound.Enabled) ws.NextInterval = tval;
else {
    ws.NextInterval = 0;
    timerHeartBeatSound.Interval = tval;
}

And in the Tick event handler you need to check if you have to make the new interval effective:

private void PlayHeartBeatSound(object sender, EventArgs e)
{
    if (ws.NextInterval != 0) timerHeartBeatSound.Interval = ws.NextInterval;
    ws.NextInterval = 0;
    Console.Beep();   
}

Upvotes: 3

Sam Hobbs
Sam Hobbs

Reputation: 2891

Try the following, except instead of "ASecond" use the number of milliseconds corresponding to the current heart rate. This will recalculate the number of milliseconds until the next beat, based on the current rate and do it for every beat. I hope it is smoother.

DateTime LastTime = DateTime.Now;

...

DateTime NextTime = LastTime + ASecond;
// Just in case we have gone past the next time (perhaps you put the system to sleep?)
if (DateTime.Now > NextTime)
    NextTime = DateTime.Now + ASecond;
TimeSpan Duration = NextTime - DateTime.Now;
LastTime = NextTime;
timer1.Interval = (int)Duration.TotalMilliseconds;

Upvotes: 0

Related Questions