c# - 在 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 毫秒打勾?
解决方案
@iPirat 是正确的,但我想其他人没有理解他的意思,所以让我先解释一下问题是什么,然后再解释一下如何解决。
在DispatcherTimer
WPF 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
推荐阅读
- java - spring-kafka Multiple @KafkaListener 具有不同的 Json 对象不起作用
- python - Powershell 中的重复输出
- string - 如何订购长度为 N 和 2 位的字符串?
- java - android listview doinbackground 不能显示任何东西
- vue.js - Vuetify v-file-input“onchange”工作但没有得到事件
- php - 使用 jquery load() 包含将 html 表提交回主页的 php 页面
- c# - 如何在 Wpf 状态栏上显示当前日期和时间
- c++ - 如何在 std::getline 中自定义分隔符
- c++ - UE4 - 检测计算着色器完成
- python - 如何删除json数据python中的特殊字符