我正在使用WPF制作一个非常简单的秒表,但使用System.Diagnostics
秒表非常慢且根本不可靠,相比我的系统时钟每1秒我的应用程序在实际时钟上是3秒。
我做了一些关于秒表缓慢的搜索,发现了很多结果但没有解决方案,所以我决定拿出自己的计数器。
以下是我提出的一个示例:
System.Windows.Threading.DispatcherTimer _update;
DateTime _started;
bool isRunning = false;
更新主题:
_update = new System.Windows.Threading.DispatcherTimer(new TimeSpan(0, 0, 0, 0, 1), System.Windows.Threading.DispatcherPriority.Normal, delegate
{
if (isRunning)
iTimer.Content = new DateTime((DateTime.Now - _started).Ticks).ToString("HH:mm:ss");
}, this.Dispatcher);
我有2个按钮,bToggle可用于启动,停止和恢复它,另一个按钮叫做bReset。
private void bReset_Click(object sender, RoutedEventArgs e)
{
isRunning = false;
iTimer.Content = "00:00:00";
bToggle.Content = "Start";
}
private void bToggle_Click(object sender, RoutedEventArgs e)
{
if ((string)bToggle.Content == "Start")
{
isRunning = true;
_started = DateTime.Now;
bToggle.Content = "Stop";
}
else if ((string)bToggle.Content == "Resume")
{
isRunning = true;
bToggle.Content = "Stop";
}
else
{
isRunning = false;
bToggle.Content = "Resume";
}
}
它可以正常启动和重置,但由于我正在使用实际时间,如果我停止并恢复,它将跳秒直到实际时间。
我怎样才能解决这个问题,或者是否有替代秒表的当前时间实际上具有良好的准确性?
答案 0 :(得分:2)
您需要引入一个额外的变量TimeSpan accumulatedTime
,在其中您可以在有人点击停止时保存已用时间间隔。
和
iTimer.Content = (new DateTime((DateTime.Now - _started).Ticks) + accumulatedTime).ToString("HH:mm:ss");
答案 1 :(得分:1)
使用System.Timers.Timer
您可以启动和停止此操作,并在计时器刻度事件中设置计数器。
这是一个简单的例子:
public partial class MainWindow : Window
{
private Timer _timer;
private int _time;
public MainWindow()
{
InitializeComponent();
_time = 0;
_timer = new Timer(1000);
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
}
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
_time++;
tbTime.Text = _time.ToString();
}));
}
private void btnStartStop_Click(object sender, RoutedEventArgs e)
{
if (_timer.Enabled)
{
_timer.Stop();
}
else
{
_timer.Start();
}
}
}
的Xaml:
<Grid>
<StackPanel>
<Button Name="btnStartStop" Content="start/stop timer" Click="btnStartStop_Click" />
<TextBlock Name="tbTime" Text="00:00" />
</StackPanel>
</Grid>
答案 2 :(得分:0)
我认为这一行是你的问题:
_update = new System.Windows.Threading.DispatcherTimer(new TimeSpan(0, 0, 0, 0, 1), System.Windows.Threading.DispatcherPriority.Normal
它告诉WPF你希望你的委托每秒执行1000次,并以第二高的优先级安排它。这比Render
和DataBind
具有更高的优先级,我认为需要Render和DataBind来实际显示放在iTimer.Content
中的更新值。
您应该将DispatcherPriority设置为Background并使用较低的频率(例如20 ms - 无论如何,人类看不到任何超过50 fps的速度。)