【发布时间】:2021-06-23 02:43:41
【问题描述】:
我制作了一个简单的WPF 全屏并始终在顶部窗口,它有一个带有dddd dd MMMM yyyy HH:mm:ss 时间戳的时钟。该应用程序在始终在触摸屏上打开 24/24,问题是 一段时间后我看到时钟在某个时间冻结。应用程序本身并没有冻结,因为我放了一些按钮,它完全可以工作。
如何更新时钟文本框
在所有版本的时钟中,我都有同样的问题!
1。任务版本
private Task _clock;
private void LoadClock()
{
_clockCancellationTokenSource = new CancellationTokenSource();
_clock = Task.Run(async () =>
{
try
{
while (!_clockCancellationTokenSource.IsCancellationRequested)
{
DateTime now = DateTime.Now;
_ = Dispatcher.InvokeAsync(() =>
{
txtHour.Text = DateTime.Now.ToString("HH:mm:ss", CultureInfo.CurrentCulture);
txtDate.Text = now.ToString("dddd dd MMMM yyyy", CultureInfo.CurrentCulture);
},
DispatcherPriority.Normal);
await Task.Delay(800, _clockCancellationTokenSource.Token);
}
}
catch
{
// I don't do anything with the errors here, If any
}
}, _clockCancellationTokenSource.Token);
}
在Page_Unloaded事件中:
if (_clock != null && !_clock.IsCompleted)
{
_clockCancellationTokenSource?.Cancel();
_clock.Wait();
_clock.Dispose();
_clockCancellationTokenSource?.Dispose();
}
2。 DispatcherTimer 版本
private DispatcherTimer _clock;
private void LoadClock(bool show)
{
_clock = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1)
};
_clockTimer_Tick(null, null);
_clock.Tick += _clockTimer_Tick;
_clock.Start();
}
private void _clockTimer_Tick(object sender, object e)
{
var now = DateTime.Now;
txtHour.Text = DateTime.Now.ToString("HH:mm:ss", CultureInfo.CurrentCulture);
txtDate.Text = now.ToString("dddd dd MMMM yyyy", CultureInfo.CurrentCulture);
}
在Page_Unloaded事件中:
if (_clock != null)
{
_clock.Stop();
_clock.Tick -= _clockTimer_Tick;
}
3。 System.Timers.Timer 版本
private Timer _clock;
private void LoadClock(bool show)
{
// Timer per gestire l'orario
_clock = new Timer(800);
_clock.Elapsed += _clock_Elapsed;
_clock.Start();
_clock_Elapsed(null, null);
}
private void _clock_Elapsed(object sender, ElapsedEventArgs e)
{
DateTime now = DateTime.Now;
Dispatcher.Invoke(() =>
{
txtHour.Text = DateTime.Now.ToString("HH:mm:ss", CultureInfo.CurrentCulture);
txtDate.Text = now.ToString("dddd dd MMMM yyyy", CultureInfo.CurrentCulture);
});
}
在Page_Unloaded事件中:
_clock.Stop();
_clock.Elapsed -= _clock_Elapsed;
_clock.Dispose();
到目前为止我所尝试的:
- 如您从我的代码中看到的那样更改计时器实现
- 在定时器
tick回调中添加日志以查看它是否由于UI调度问题或定时器问题而停止。有趣的是,我看到计时器在一定时间后停止计时。 - 我认为这可能是 Windows 的问题,可能会停止额外的线程,但我没有找到任何线索!
你有什么建议吗?
【问题讨论】:
-
您的问题是您缺少异常。永远不要吞下异常。添加一些适当的错误处理代码。
-
另外,您不需要使用
Task.Run或Invoke,因为 WPF 会为您添加自己的同步上下文。 -
延迟 800 毫秒会给你一个 janky UI。您应该使用 500 毫秒,或 1 秒的某个整数部分。 500ms 是您可以使用的最高延迟(和最低频率)。你需要阅读Nyquist frequency
标签: c# wpf dispatchertimer system.timers.timer