   VC# windows.forms.timer problem
  I'm trying to create an array of timer events that can be controlled individually using one timer. It works great and the way I'd expect it to until one of the timed events is reset.For example, one of the entries is set to repeat once every 5 seconds. When it gets to zero it updates perfectly but then very quickly goes down to 4 and repeats.I have no idea what's causing this and have looked into all I can think of. I know it's not the timer's interval as it's ticking every 200ms... though I'm no expert in timers, hence why I'm trying this thing out, maybe I'm doing it wrong?Anyway, here is the code, sorry that I don't know how to format the code. It has a default label and timer:public partial class Form1 : Form{Dictionary<string, TimeInfo> timers = new Dictionary<string, TimeInfo>();public Form1(){InitializeComponent();timer1.Interval = 100;timer1.Tick += new EventHandler(timer1_Tick);Load += new EventHandler(Form1_Load);FormClosing += new FormClosingEventHandler(Form1_FormClosing);timers.Add("1st", new TimeInfo(TimeSpan.FromSeconds(5), true));timers.Add("2nd", new TimeInfo(TimeSpan.FromSeconds(35), false));timers.Add("3rd", new TimeInfo(TimeSpan.FromMinutes(2), true));}void Form1_Load(object sender, EventArgs e) { timer1.Start(); }void Form1_FormClosing(object sender, FormClosingEventArgs e) { timer1.Stop(); }string timerInfo;TimeSpan timeLeft;void timer1_Tick(object sender, EventArgs e){timerInfo = "";DateTime now = DateTime.Now;string[] keys = timers.Keys.ToArray();foreach (string key in keys){if (timers[key].Expires < now){if (timers[key].Repeat)timers[key] = new TimeInfo(timers[key].TimeToAdd, true);elsetimers.Remove(key);}if (timers.ContainsKey(key)){timeLeft = timers[key].Expires.Subtract(now);switch (key){case "1st": timerInfo += "1st: " + timeLeft.Minutes + ":" + timeLeft.Seconds; break;case "2nd": timerInfo += "2nd: " + timeLeft.Minutes + ":" + timeLeft.Seconds; break;case "3rd": timerInfo += "3rd: " + timeLeft.Minutes + ":" + timeLeft.Seconds; break;}timerInfo += Environment.NewLine;}}label1.Text = timerInfo;}}struct TimeInfo{DateTime _expires;internal DateTime Expires { get { return _expires; } }bool _repeat;internal Boolean Repeat { get { return _repeat; } }TimeSpan _addtime;internal TimeSpan TimeToAdd { get { return _addtime; } }public TimeInfo(TimeSpan timetoadd, Boolean repeat){_repeat = repeat;_addtime = timetoadd;_expires = DateTime.Now.Add(timetoadd);}}[Edited by - Nyight on April 21, 2010 3:28:22 PM]
  Alright I figured out what the problem was so here is the answer in case someone else comes across this problem.It's working perfectly as it is. The reason why it quickly goes from the number you assign down to the next one is because it's only on that top number for 1 millisecond.For example if it's set to repeat every 5 seconds, the timespan its given is 5 seconds and 000 milliseconds. So when the update occurs again in 200ms, it's equivocally 4 seconds and 800 milliseconds. When you request the seconds, it comes back as 4. Thus the flicker occurs.To compensate for this I modified the struct to have seconds and allow me to use Math.Ceiling() on the milliseconds and then add it to the seconds so it's essentially rounding up until the second officially ends. So 4.8 and 4.3 = 5 and so forth:internal int Seconds { get { return TimeLeft.Seconds + (int)Math.Ceiling((double)TimeLeft.Milliseconds / 1000); } }I also changed things around in the code as a whole to simplify things. If I'm doing something incorrectly, improperly or even if there is a better/faster technique, PLEASE tell me. I'd rather learn to code correctly the first time than to learn the wrong way and have to relearn the correct way.public partial class Form1 : Form{Dictionary<string, TimeInfo> timers = new Dictionary<string, TimeInfo>();public Form1(){InitializeComponent();timer1.Interval = 100;timer1.Tick += new EventHandler(timer1_Tick);Load += new EventHandler(Form1_Load);FormClosing += new FormClosingEventHandler(Form1_FormClosing);timers.Add("1st", new TimeInfo(TimeSpan.FromSeconds(5), true));//timers.Add("2nd", new TimeInfo(TimeSpan.FromSeconds(35), false));//timers.Add("3rd", new TimeInfo(TimeSpan.FromMinutes(2), true));}void Form1_Load(object sender, EventArgs e) { timer1.Start(); }void Form1_FormClosing(object sender, FormClosingEventArgs e) { timer1.Stop(); }string timerInfo;void timer1_Tick(object sender, EventArgs e){timerInfo = "";DateTime now = DateTime.Now;string[] keys = timers.Keys.ToArray();foreach (string key in keys){if (timers[key].Expired){if (timers[key].Repeat)timers[key] = new TimeInfo(timers[key].TimeToAdd, true);elsetimers.Remove(key);}if (timers.ContainsKey(key)){switch (key){case "1st": timerInfo += "1st: " + timers[key].Minutes + ":" + timers[key].Seconds; break;case "2nd": timerInfo += "2nd: " + timers[key].Minutes + ":" + timers[key].Seconds; break;case "3rd": timerInfo += "3rd: " + timers[key].Minutes + ":" + timers[key].Seconds; break;}timerInfo += Environment.NewLine;}}label1.Text = timerInfo;}}struct TimeInfo{DateTime _expires;internal Boolean Expired { get { return (_expires <= DateTime.Now) ? true : false; } }internal TimeSpan TimeLeft { get { return _expires.Subtract(DateTime.Now); } }internal int Seconds { get { return TimeLeft.Seconds + (int)Math.Ceiling((double)TimeLeft.Milliseconds / 1000); } }internal int Minutes { get { return TimeLeft.Minutes; } }bool _repeat;internal Boolean Repeat { get { return _repeat; } }TimeSpan _addtime;internal TimeSpan TimeToAdd { get { return _addtime; } }public TimeInfo(TimeSpan timetoadd, Boolean repeat){_repeat = repeat;_addtime = timetoadd;_expires = DateTime.Now.Add(timetoadd);}}