Reputation: 580
I have implemented a DispatcherTimer with databinding which would act like a stopwatch or counting timer to display the time elapsed during an audio call. (as you can see in your mobile phones)
The following code is becoming slow for every minute by "1 second" which is not good in calculating the bill. Can you please tell me where I am wrong ?
System.Windows.Threading.DispatcherTimer dispatcherTimer;
int seconds = 0;
public string Counter { get; set; }
public Timer()
{
InitializeComponent();
this.DataContext = this;
dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
Counter = (seconds / 3600).ToString() + ":" + (seconds / 60).ToString("00") + ":" + (seconds % 60).ToString("00");
NotifyPropertyChanged("Counter");
seconds++;
}
I compared this timer with other stop watches both in Internet and also in mobile, this timer is getting delayed by a second for each minute.
Upvotes: 1
Views: 2178
Reputation: 13501
You are relying on the timer, and it seems to be consistently inaccurate by the same amount.
Why don't you take a point in time and store that,
private DateTime startTime;
public Timer()
{
InitializeComponent();
startTime = DateTime.Now;
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
Counter = (DateTime.Now - startTime).ToString();
...
}
Actually taking the code like this shows why you are having a problem. The ToString method there shows the counter more accurately including milliseconds, and it turns out the timer is not firing every 1 second, but more like every 1.01 seconds.
I am getting values like this,
1.008
1.02
1.031
1.03901
etc.
You can then replace the above with this,
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
TimeSpan elapsedTime = (DateTime.Now - startTime);
Counter = string.Format("{0:hh\\:mm\\:ss}", elapsedTime);
And it will be formatted like you had it before with no milliseconds.
Upvotes: 4
Reputation: 77687
You aren't guaranteed to have the event fire at exactly 1000ms interval. You should calculate the seconds in the event rather than incrementing your own field that holds seconds
Upvotes: 1