秒表的替代品?

时间:2012-05-04 10:47:09

标签: c# wpf stopwatch

我正在使用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";
    }
}

它可以正常启动和重置,但由于我正在使用实际时间,如果我停止并恢复,它将跳秒直到实际时间。

我怎样才能解决这个问题,或者是否有替代秒表的当前时间实际上具有良好的准确性?

3 个答案:

答案 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次,并以第二高的优先级安排它。这比RenderDataBind具有更高的优先级,我认为需要Render和DataBind来实际显示放在iTimer.Content中的更新值。

您应该将DispatcherPriority设置为Background并使用较低的频率(例如20 ms - 无论如何,人类看不到任何超过50 fps的速度。)