【问题标题】:WPF DispatcherTimer doesn't keep time when resumedWPF DispatcherTimer 在恢复时不计时
【发布时间】:2015-06-02 11:33:33
【问题描述】:

当您在 DispatcherTimer 中将属性 IsEnabled 设置为 false 时,是否假定计时器在后台保持其状态,或者改为停止并重置?在以下示例中,定时器间隔为 5 秒,如果您运行应用程序并在 4 秒时单击按钮以禁用定时器,并且如果在 7 秒时再次单击按钮以启用它(例如),则定时器事件不是在 8 秒后一秒触发,而是在 12 秒 = 7 秒 + 5 秒触发。似乎 timer.IsEnabled=false 重置了计时器间隔。禁用时有任何替代方法保持计时器状态吗?

应用程序有两个标签 timerLabel 和 statusLabel 以及按钮。我在这里没有足够的声望点来发布图片。

namespace WpfApplication1 {

public partial class MainWindow : Window {

    public MainWindow() {
        InitializeComponent();
    }

    int ticksCounter = 0;  

    System.Windows.Threading.DispatcherTimer timer;

    private void Window_Loaded(object sender, RoutedEventArgs e) {
        timer = new System.Windows.Threading.DispatcherTimer();
        timer.Tick += new EventHandler(timer_Tick);
        timer.Interval = new TimeSpan(0, 0, 0, 5, 0);  // Sets 5 s. interval
        timer.Start();
    }

    private void timer_Tick(object sender, EventArgs e) {
        ticksCounter ++;
        timeLabel.Content = "Ticks = " + ticksCounter.ToString();
    }

    private void button_Click(object sender, RoutedEventArgs e) {
        if (timer.IsEnabled) {
            timer.IsEnabled = false;
            statusLabel.Content = "OFF";
            boton.Content = "Enable";
        }
        else {
            timer.IsEnabled = true;
            statusLabel.Content = "ON";
            boton.Content = "Disable";
        }
    }

}
}

【问题讨论】:

标签: c# wpf timer


【解决方案1】:

DispatcherTimer 总是在重启时重新开始计时,无论是通过调用Start() 还是将IsEnabled 设置为true。如果您希望计时器从间隔中间恢复,您需要自己实现。例如,通过维护一个Stopwatch 来测量自最近一次滴答以来经过的时间,并在您重新启动它时减去第一个间隔的时间,从而在Tick 事件处理程序中将间隔恢复为所需的常规间隔。

这是一个说明基本思想的代码示例:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        _timer = new DispatcherTimer();
        _timer.Tick += _timer_Tick;
    }

    void _timer_Tick(object sender, EventArgs e)
    {
        _timer.Interval = _baseInterval;
        _stopWatch.Restart();
    }

    private TimeSpan _baseInterval = TimeSpan.FromSeconds(5);
    private DispatcherTimer _timer;
    private Stopwatch _stopWatch = new Stopwatch();

    // Call from appropriate location to toggle timer, e.g. in a button's
    // Click event handler.
    private void ToggleTimer()
    {
        if (_timer.IsEnabled)
        {
            _timer.IsEnabled = false;
            _stopWatch.Stop();
            button1.Content = "Start";
        }
        else
        {
            _timer.Interval = _baseInterval - _stopWatch.Elapsed;
            _stopWatch.Restart();
            _timer.IsEnabled = true;
        }
    }
}

【讨论】:

  • 谢谢。秒表的添加解决了这个问题。
【解决方案2】:

我知道它已经过去了很长时间,但我正在使用这个示例并注意到要使它正确,您需要 1 个小改动。

ToogleTimer() 函数中,而不是调用 _stopWatch。Restart() 调用 _stopWatch.Start()

不同之处在于,在上面的代码中,如果您在 1 个间隔内暂停更多次,则会产生副作用,因为每次恢复秒表时都会重置(它应该只在 dispathcer 的 Tick 事件内重置)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多