wpf DispatcherTimer 显示秒数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15687523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DispatcherTimer for displaying seconds
提问by creatiive
I am trying to display a simple second counter. I have a dispatchertimer with a tick interval of 1 second and a textbox which I update in the tick handler with the current amount of seconds. There is a tiny amount of work in the tick handler, namely a call to 'tostring()' on some ints.
我正在尝试显示一个简单的第二个计数器。我有一个刻度间隔为 1 秒的 dispatchertimer 和一个文本框,我在刻度处理程序中用当前的秒数更新它。滴答处理程序中有少量工作,即对某些整数调用“tostring()”。
My issue is that the seconds are slower than they should be. Even if I set the interval to 100 milliseconds and make a check when elapsed, it is still slower than it should be. (over the course of a minute it is roughly 6 seconds slow).
我的问题是秒数比它们应该的慢。即使我将间隔设置为 100 毫秒并在经过时进行检查,它仍然比应有的速度慢。(在一分钟的过程中,它大约慢了 6 秒)。
Can anyone point me in the right direction for displaying a second counter that is accurate?
任何人都可以指出我正确的方向来显示第二个准确的计数器吗?
EDIT: Some code here (in .xaml.cs). It is taken from an example which works fine. The difference is that I am setting the Text property of a TextBox, rather than a Value property of another control.
编辑:这里的一些代码(在 .xaml.cs 中)。它取自一个工作正常的例子。不同之处在于我设置的是 TextBox 的 Text 属性,而不是另一个控件的 Value 属性。
...
this.timer.Interval = TimeSpan.FromMilliseconds(100);
...
private void OnDispatcherTimer_Tick(object sender, EventArgs e) {
if (this.currentValue > TimeSpan.Zero) {
this.currentValue = this.currentValue.Value.Subtract(TimeSpan.FromMilliseconds(100));
} else {
// stop timer etc
}
this.seconds.Text = this.currentValue.Value.Seconds.ToString();
}
回答by Kevin Gosse
Your way of keeping track of time is flawed. You're incrementing a counter each time the timer ticks, but there's no guarantee your timer will execute every 100 ms. And even if it did, you'd have to take into account the execution time of your code. Therefore, no matter what you do, your counter will drift.
你记录时间的方式有缺陷。每次计时器滴答时,您都会增加一个计数器,但不能保证您的计时器每 100 毫秒执行一次。即使这样做了,您也必须考虑代码的执行时间。因此,无论您做什么,您的计数器都会漂移。
What you must do is storing the date at which you started your counter. Then, every time the timer ticks, you compute the number of seconds that have elapsed:
您必须做的是存储您开始计数器的日期。然后,每次计时器滴答作响,您计算已经过去的秒数:
private DateTime TimerStart { get; set; }
private void SomePlaceInYourCode()
{
this.TimerStart = DateTime.Now;
// Create and start the DispatcherTimer
}
private void OnDispatcherTimer_Tick(object sender, EventArgs e) {
var currentValue = DateTime.Now - this.TimerStart;
this.seconds.Text = currentValue.Seconds.ToString();
}
回答by Damian Jarosch
If you care about precise time a dispatchertimer is not good choice.
如果您关心精确时间,调度员计时器不是一个好的选择。
I thing you should separate counting seconds(time) and displaying on screen.
我认为你应该分开计数秒(时间)和在屏幕上显示。
Use a System.Threading.Timer and use Dispatcher.BeginInvoke() in Timer callback.
使用 System.Threading.Timer 并在 Timer 回调中使用 Dispatcher.BeginInvoke() 。
simple example:
简单的例子:
public partial class MainPage : PhoneApplicationPage
{
private DateTime _startDate;
private int _secondDuration;
private Timer _timer;
// Constructor
public MainPage()
{
InitializeComponent();
_startDate = DateTime.Now;
_secondDuration = 0;
_timer= new Timer(timerCallback, null, 0, 10);
}
private void timerCallback(object state)
{
var now = DateTime.Now;
if (now > _startDate + TimeSpan.FromSeconds(1))
{
_secondDuration += 1;
_startDate = now;
Dispatcher.BeginInvoke(() => { Counter.Text = _secondDuration.ToString(); });
}
}
}
After every 10 milisecond timer checks for one second has elapsed and print to textbox elapsed seconds
每 10 毫秒计时器检查一秒过去后并打印到文本框经过的秒数
or you can do this like:
或者你可以这样做:
public partial class MainPage : PhoneApplicationPage
{
private Timer _timer;
private int _secondDuration;
// Constructor
public MainPage()
{
InitializeComponent();
_timer = new Timer(timerCallback, null, 0, 1000);
}
private void timerCallback(object state)
{
_secondDuration += 1;
Dispatcher.BeginInvoke(() => { Counter.Text = _secondDuration.ToString(); });
}
}

