Im creating ccountdown timer in xamarin.forms. 
The problem is when I pause the timer and next I’ll start the timer, it speeds up and slows down and it happens the whole time. It should goes every second but why does it speed up sometimes ever 2/4 seconds ?
The code below:
bool Value =false;
int counter =120;
private void RunTimer(Boolean Value)
{
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
If(Value)
{
counter--;
if(counter <=0)
{
counter = 120;
MainText.Text = dt.AddSeconds(counter).ToString("mm:ss");
}
MainText.Text = dt.AddSeconds(counter).ToString("mm:ss");
}
return true;
}
return false;
});
private void Start_Pause(object sender, EventArgs e)
{
if(value == false)
{
RunTimer(true);
Value = true;
}
else
{
RunTimer(false);
Value = false;
}
}
>Solution :
MainText.Text = dt.AddSeconds(counter).ToString("mm:ss"); <– This is incorrect. Computer timers are never precise. Instead compute the DateTime end value once, and recompute remaining time by subtracing DateTime.Now on every tick (instead of counting imprecise time periods yourself).
Change your code to something like this:
private void RunTimer(Boolean value)
{
DateTime start = DateTime.Now;
DateTime end = start.AddSeconds( 120 );
Device.StartTimer( TimeSpan.FromMilliseconds( 100 ), () =>
{
TimeSpan remaining = end - DateTime.Now;
Device.BeginInvokeOnMainThread( () =>
{
this.MainText.Text = remaining.ToString("mm:ss");
});
return remaining >= TimeSpan.Zero;
});
}
- I’m using
TimeSpan.FromMilliseconds( 100 )to ensure the label’s text is invalidated closer to when theremainingvalue actually changes to counteract jitter in the system. - Using
return remaining >= TimeSpan.Zero;will stop the countdown as soon asendis passed. - The documentation says that all UI interactions inside
StartTimermust be done withDevice.BeginInvokeOnMainThread.