我有一个工作正常的计时器,我遇到的问题是当应用程序处于睡眠模式或最小化时,或者当我按下后退按钮时,计时器应该只在我按下停止按钮时停止。
/// <summary>
/// Starts the timer
/// </summary>
private void StartCommandAction()
{
CancellationTokenSource cts = _cancellationTokenSource; // safe copy
Device.StartTimer(TimeSpan.FromSeconds(1),() =>
{
if (cts.IsCancellationRequested)
{
return false;
}
else
{
Device.BeginInvokeOnMainThread(() =>
{
var totalTimeInt = string.IsNullOrEmpty(TxtTotalTime.Value) ? 0 : int.Parse(TxtTotalTime.Value);
var totalSec = (int)TotalSeconds.TotalSeconds;
TimeSpan _TimeSpan = new TimeSpan(totalTimeInt, 0, totalSec); //TimeSpan.FromSeconds(TotalSeconds.TotalSeconds);
LblTime = string.Format("{0:00}:{1:00}:{2:00}", _TimeSpan.Hours, _TimeSpan.Minutes, _TimeSpan.Seconds);
IsVisibleTimerLabel = true;
Count();
});
return true;
}
});
IsVisibleButtonStart = false;
IsVisibleButton = true;
}
在不了解源代码的其余部分的情况下,我突然想到:您期望计时器事件每秒恰好引发一次,并使用文本表示来计算总时间。这可能适用于当前的定时器实现,但不能保证。更糟糕的是,您的实现对于不同的定时器实现并不健壮。
当你在每次迭代中总结你的时间时,总时间的误差会越来越大。根据您的用例,这可能无关紧要,但幸运的是,解决这个问题的方法也是解决您试图解决的问题的方法。
我的建议是:不要总结时代,而是引入一个固定的参考。按照第一个顺序,这可能是DateTime
(如果精度对你来说很重要,你的解决方案看起来会有所不同,因此DateTime.Now
的精度就可以了(,但Stopwatch
也可以。
首次启动计时器时,将当前DateTime.Now
值存储在成员变量中,并使用该值计算经过时间
CancellationTokenSource cts = _cancellationTokenSource; // safe copy
this._startedAt = DateTime.Now;
Device.StartTimer(TimeSpan.FromSeconds(1),() =>
{
if (cts.IsCancellationRequested)
{
return false;
}
else
{
Device.BeginInvokeOnMainThread(() =>
{
TimeSpan _TimeSpan = DateTime.Now - _startedAt;
LblTime = _TimeSpan.ToString("hh:mm:ss);
IsVisibleTimerLabel = true;
Count();
});
return true;
}
});
(请注意:要格式化TimeSpan
,您可以使用带有格式字符串的ToString
方法。请参阅TimeSpan.ToString
的文档,了解如何根据您的需要格式化TimeSpan
值(
这样,当返回到页面时,您只需重新启动计时器(不过不需要设置_startedAt
(。因为您已经设置了_startedAt
,所以计时器将继续运行并显示正确的时间。