Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 毫秒精确定时器#_C#_Wpf_Timer - Fatal编程技术网

C# 毫秒精确定时器#

C# 毫秒精确定时器#,c#,wpf,timer,C#,Wpf,Timer,我使用的是一个timer类(包装在System.Timers.timer),我想用它在WPF窗口中显示2分钟的倒计时,精确到每10毫秒一次。基本上,我希望以mm\\\:ss\\.ff格式显示一个字符串,该字符串每10毫秒更新一次。以下是我的课程: using System; using System.Timers; using Proj.Utilities.Extensions; namespace Proj.Framework { /// <summary> /// Counts

我使用的是一个timer类(包装在
System.Timers.timer
),我想用它在WPF窗口中显示2分钟的倒计时,精确到每10毫秒一次。基本上,我希望以
mm\\\:ss\\.ff
格式显示一个字符串,该字符串每10毫秒更新一次。以下是我的课程:

using System;
using System.Timers;
using Proj.Utilities.Extensions;

namespace Proj.Framework
{
/// <summary>
/// Counts down in wall time, raising events at a specified updated period.
/// </summary>
public sealed class MillisecondTimer
{
    private readonly TimeSpan _initialTime;
    private readonly Timer _timerRep;
    private TimeSpan _timeRemaining;

    /// <summary>
    /// The time remaining in the countdown.
    /// </summary>
    public TimeSpan TimeRemaining
    {
        get { return _timeRemaining; }
        private set
        {
            _timeRemaining = value;
            if (_timeRemaining <= TimeSpan.Zero)
            {
                InvokeCountDownElapsed();
            }
        }
    }

    /// <summary>
    /// True if the timer is currently counting down; false otherwise.
    /// </summary>
    public bool IsCountingDown => _timerRep.Enabled;

    /// <summary>
    /// Raised every time the update period elapses.
    /// </summary>
    public event EventHandler TimeChanged;

    /// <summary>
    /// Raised when the entire countdown elapses.
    /// </summary>
    public event EventHandler CountDownElapsed;

    /// <summary>
    /// Creates a new CountDownTimer.
    /// </summary>
    /// <param name="countDownTime">
    /// The amount of time the timer should count down for.
    /// </param>
    /// <param name="updatePeriod">
    /// The period with which the CountDownTimer should raise events.
    /// </param>
    public MillisecondTimer(TimeSpan countDownTime, TimeSpan updatePeriod)
    {
        _initialTime = countDownTime;
        _timerRep = new Timer(10) { AutoReset = true };


        AttachEventHandlers();
    }

    private void AttachEventHandlers()
    {
        AttachedElapsedEventHandler();
        AttachCountDownElapsedEventHandler();
    }

    private void AttachedElapsedEventHandler()
    {
        _timerRep.Elapsed += OnElapsed;
    }

    private void AttachCountDownElapsedEventHandler()
    {
        CountDownElapsed += OnCountDownElapsed;
    }

    private void InvokeTimeChanged()
    {
        //Defined in Proj.Utilities.Extentions
        TimeChanged.InvokeIfInstantiated(this, new EventArgs());
    }

    private void InvokeCountDownElapsed()
    {
        CountDownElapsed.InvokeIfInstantiated(this, new EventArgs());
    }

    private void OnElapsed(object sender, ElapsedEventArgs e)
    {
        TimeRemaining -= TimeSpan.FromMilliseconds(10);
        InvokeTimeChanged();
    }

    private void OnCountDownElapsed(object sender, EventArgs e)
    {
        Stop();
    }

    /// <summary>
    /// Restarts the countdown.
    /// </summary>
    public void Restart()
    {
        TimeRemaining = _initialTime;
        _timerRep.Start();
        InvokeTimeChanged();
    }

    /// <summary>
    /// Stops the countdown.
    /// </summary>
    public void Stop()
    {
        _timerRep.Stop();
    }
}
}
使用系统;
使用系统计时器;
使用Proj.Utilities.Extensions;
命名空间项目框架
{
/// 
///墙时间倒计时,在指定的更新周期引发事件。
/// 
公共密封类毫秒计时器
{
私有只读时间跨度_initialTime;
专用只读计时器\u timerRep;
专用时间跨度(u timelexing);;
/// 
///倒计时中剩余的时间。
/// 
公共时间跨度剩余时间
{
获取{return\u timeRemaining;}
专用设备
{
_剩余时间=价值;
如果(\u timeRemaining\u timerRep.Enabled;
/// 
///每次更新周期结束时引发。
/// 
公共事件事件处理程序时间已更改;
/// 
///在整个倒计时结束时引发。
/// 
公共事件事件处理程序倒计时已过;
/// 
///创建一个新的倒计时。
/// 
/// 
///计时器应倒计时的时间量。
/// 
/// 
///倒计时计时器引发事件的时间段。
/// 
公共毫秒计时器(TimeSpan countDownTime,TimeSpan updatePeriod)
{
_初始时间=停机时间;
_timerRep=新定时器(10){AutoReset=true};
AttachEventHandlers();
}
私人无效附件
{
AttachedElapsedEventHandler();
AttachCountDownElapsedEventHandler();
}
私有无效附件DELAPSEDEVENTHANDLER()
{
_timerRep.Appeased+=一次失效;
}
私有void AttachCountDownElapsedEventHandler()附加
{
CountdownPeased+=OnCountdownPeased;
}
私有void InvokeTimeChanged()
{
//在Proj.Utilities.extensions中定义
InvokeFinStantiated(这是新的EventArgs());
}
私有void invokeCountDownAppeased()
{
InvokeFinStantiated(这是新的EventArgs());
}
私有无效失效(对象发送方,ElapsedEventArgs e)
{
剩余时间-=从毫秒开始的时间跨度(10);
InvokeTimeChanged();
}
私有void onCountDownAppeased(对象发送方,事件参数e)
{
停止();
}
/// 
///重新开始倒计时。
/// 
公共无效重新启动()
{
剩余时间=_初始时间;
_timerRep.Start();
InvokeTimeChanged();
}
/// 
///停止倒计时。
/// 
公共停车场()
{
_timerRep.Stop();
}
}
}

它是有效的,因为它做了我期望它做的事情,但是它太慢了。当我想让它从10秒开始倒计时时,大约需要15秒。最终目标是一门课,可以从2分钟开始倒计时,准确地说,分辨率为10毫秒。为什么这比它应该做的要长,我该怎么做才能让它工作得更好er?

不要每次更改您的
剩余时间
-保留开始时间并与当前时间进行比较,以获得
剩余时间

TimeRemaining = (DateTime.Now - _initialTime);

这样一来,您从
计时器中得到的任何错误都不会累积,但最终会趋于平衡。

我曾经在多媒体计时器API周围编写了一个包装器,可以精确到1ms,请参见。未针对生产使用进行测试,因此请注意清空


然而,我觉得你的方法不正确。问问你自己,你是否真的需要精确的10毫秒计时来显示2分钟间隔的倒计时。你似乎把两个责任放在计时器上。保持准确的时间和定期引发事件。计时器只适用于这两种情况中的后一种。使用
秒表
来保持时间准确。使用计时器从秒表中获取经过的时间,并定期更新显示。这样,无论计时器的准确度如何,时间都会保持准确。用户不会注意到计时器经过的时间有细微的偏差,也不会关心它是否每10或20毫秒更新一次。

一些相关信息e“精确到每10毫秒”不适用于windows,我认为最小分辨率约为15毫秒,调度/抢占可以推得更高。您可能会看到结果(这就是为什么10秒看起来需要15秒)。如果您需要精确的10秒计时器(具有可变更新间隔)然后您需要两个计时器,一个用于整个期间,另一个用于更新,或者与日期/时间进行比较,但这也有解决问题。太好了!唯一的问题是它需要是
var now=DateTime.now;
TimeRemaining=(\u initialTime-(now.TimeOfDay-\u start));
invoketimechaned()
这样类型就可以工作。
\u started
是调用
Restart()
方法的时间。谢谢!除了错误修复,DateTime提供的分辨率不足以满足用户的要求。@Atoms可能没有精确的规格,但大多数屏幕甚至不能显示每10毫秒(60Hz=~17MS)的更改因此,我怀疑10毫秒是一个硬性要求。