首页 > 解决方案 > 在 WPF 中显示系统时间:调度程序计时器

问题描述

我使用 DispatcherTimer 在我的应用程序中显示时间(基本上在标签 Datetime.Now 格式为 hh:mm:ss tt)。

_timer = new DispatcherTimer {Interval = new TimeSpan(0, 0, 1)};
                _timer.Tick += _timer_Tick;
                _timer.Start();

private void _timer_Tick(object sender, EventArgs e)
            {
                try
                {
                    var now = DateTime.UtcNow;
                    var nowUserSelected =
                        TimeZoneInfo.ConvertTimeFromUtc(now,
                            (DataContext as MainViewModel)?.UserSelectedTimeZone ?? TimeZoneInfo.Local);
                    ClockCurrent.Text = $"{nowUserSelected:hh:mm:ss tt}";
                }
                catch (Exception exp)
                {
                    Log.Error("Error occurred while reporting time", exp);
                }
            }

问题是,如果用户从任务栏中打开时钟(如果您单击任务栏中的时间,则会弹出显示当前时间(包括秒数)的弹出窗口),有时我的应用程序中的时间似乎关闭了一个第二(有时!)。我相信这可能会发生,因为必须将计时器设置为从当前时间开始每秒滴答一次,这可能是晚上 10:50:53 和 950 毫秒,可以说,然后它每 54 和 950 毫秒滴答一次...... .. ms 等等,因为我只显示时间直到几秒钟,所以它给人一种我落后一秒钟的错觉。

显示与任务栏显示的时间相匹配的时间的推荐方法是什么,也许将计时器间隔设置为每 500 毫秒打勾?

标签: c#.netwpf

解决方案


@iPirat 是正确的,但我想其他人没有理解他的意思,所以让我先解释一下问题是什么,然后再解释一下如何解决。

DispatcherTimerWPF GUI 线程上运行。这样做的好处是代码DispatcherTimer.Tick可以访问任何 WPF 控件。缺点是,一旦自上次滴答声过去 1 秒后,WPF GUI 线程可能正忙于其他事情,滴答声会在几毫秒后触发。下一次 Tick 被执行时,会有另一个小的延迟,这个延迟会累积起来,直到总的延迟大于 1 秒并且你“失去”了一个 tick。

DispatcherTimer.Interval您可以通过在每个滴答期间进行更改来防止这种情况。如果您希望每 1000 毫秒执行一次刻度,并且该刻度执行得太晚 x 毫秒,则设置DispatcherTimer.Interval为 1000-x 毫秒。

const int constantInterval = 1000;//milliseconds

private void Timer_Tick(object? sender, EventArgs e) {
  var now = DateTime.Now;
  var nowMilliseconds = (int)now.TimeOfDay.TotalMilliseconds;
  var timerInterval = constantInterval - 
   nowMilliseconds%constantInterval + 5;//5: sometimes the tick comes few millisecs early
  timer.Interval = TimeSpan.FromMilliseconds(timerInterval);
}

顺便说一句,您可能希望像这样增加优先级DispatcherTimer timer = new DispatcherTimer (DispatcherPriority.Input);。这将使延迟更小,但 GUI 仍然可以足够快地呈现。

有关更多详细信息,请参阅我在 CodeProject 上的文章:提高 WPF DispatcherTimer Precision


推荐阅读