代码之家  ›  专栏  ›  技术社区  ›  James Santiago

使用DispatchTimer将经过的时间精确到1毫秒

  •  5
  • James Santiago  · 技术社区  · 15 年前

    我试图用调度计时器来测量按键事件之间的时间(以毫秒为单位),但是当声明调度计时器的间隔为1毫秒,然后建立tick事件时,它并不是每1毫秒触发一次,而是大约10-100毫秒(猜测)。如果这个tick事件没有按时触发,我如何准确地以毫秒为单位测量时间?我在silverlight里做这件事,它似乎无法访问System.Timer。在System.Threading.Timer中似乎也会发生同样的情况。

    下面是代码的基本内容:

    public void StartTimer(object o, RoutedEventArgs sender)
    {
        System.Windows.Threading.DispatcherTimer myDispatcherTimer = new  
        System.Windows.Threading.DispatcherTimer();
        myDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1); // 1 Milliseconds 
        myDispatcherTimer.Tick += new EventHandler(Each_Tick);
        myDispatcherTimer.Start();
    }
    
    // A variable to count with.
    int i = 0;
    
    public void Each_Tick(object o, EventArgs sender)
    {
        i++;
    }
    
    public void keypress(object s, EventArgs args)
    {
        label1.contents = i.ToString();
        i = 0;
    }
    

    有什么想法吗?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Ken Smith    15 年前

    Silverlight中的System.Threading计时器只能精确到大约20毫秒。通常,如果需要更好的分辨率,您需要一个多媒体计时器,但不能直接在Silverlight中访问这些计时器。也就是说,通过一些重大的调整和折衷,我已经读到,有可能得到一个银光计时器,有~3ms的精度。请参阅此处引用的文档:

    http://blogs.msdn.com/b/nikola/archive/2009/08/19/exposed-5-methods-to-create-game-loop-which-is-the-best.aspx

    请注意,我并没有亲自测试所有这些替代方案,但它们值得研究。

    另一种选择是最近推出的 System.Diagnostics.Stopwatch 上课。不幸的是,这只是 有时 一个高分辨率计时器,取决于你运行的硬件。而且MS文档没有指定如何确定它是否真的是高分辨率的,所以您唯一的选择是检查is high resolution属性。

        2
  •  5
  •   Tim Lloyd    15 年前

    启动 Stopwatch 相反,只需在每次按下键时,将秒表的当前已用毫秒数从最后一个已用毫秒数中减去(您需要将其存储在变量中)。

        private Stopwatch _stopwatch;
        private int _lastElapsedMs;
    
        public void StartTimer(object o, RoutedEventArgs sender)
        {
            _lastElapsedMs = 0;
            _stopwatch = Stopwatch.StartNew();
        }
    
        public void keypress(object s, EventArgs args)
        {
            int elapsedMs = (int)_stopwatch.ElapsedMilliseconds;
            int currentElapsed = (elapsedMs - _lastElapsedMs);
    
            _lastElapsedMs = elapsedMs;
    
            label1.contents = currentElapsed.ToString();
        }