C# 消除累计误差的倒计时
2024-09-21 16:55:54
使用 C# 中自带的各种 timer 计时,都会有累计误差,以下代码实现了一种消除累计误差的方法,使得每次计时的误差,空值在 100 ms 以内(可以通过修改代码提升精度。)
对于精度要求在秒级别的简单计时应用来说,误差可接受,并且消除累计误差。
以下是代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace Xxx.Utils
{
/// <summary>
/// 带有校准功能的秒钟计时器(误差最大100ms)
/// </summary>
public class ClockTimer : IDisposable
{
private readonly Timer _driveTimer;
private int _intervalSeconds = 1;
private double _startMilliSeconds;
private long _tickCount;
private bool _enabled;
public ClockTimer()
{
_driveTimer = new Timer(100);
_driveTimer.Elapsed += DriveTimerOnElapsed;
}
public ClockTimer(int intervalSeconds) : this()
{
_intervalSeconds = intervalSeconds;
}
/// <summary>
/// 获取或设置<see cref="ClockTimer"/>的触发时间间隔,单位:秒。
/// </summary>
public int IntervalSeconds
{
get => _intervalSeconds;
set => _intervalSeconds = value < 1 ? 1 : value;
}
/// <summary>
/// 获取或设置一个值,该值指示<see cref="ClockTimer"/>是否引发<see cref="Elapsed"/>事件。
/// </summary>
public bool Enabled
{
get => _enabled;
set
{
if (value)
{
Start();
}
else
{
Stop();
}
}
}
/// <summary>
/// 到达时间间隔时发生。
/// </summary>
public event EventHandler<ElapsedEventArgs> Elapsed;
/// <summary>
/// 开始计时
/// </summary>
public void Start()
{
_driveTimer.Start();
_enabled = true;
_startMilliSeconds = TimeSpan.FromTicks(DateTime.Now.Ticks).TotalMilliseconds;
}
/// <summary>
/// 结束计时
/// </summary>
public void Stop()
{
_driveTimer.Stop();
_tickCount = 0;
_enabled = false;
}
private void DriveTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
{
double currentMilliseconds = TimeSpan.FromTicks(DateTime.Now.Ticks).TotalMilliseconds;
// 第一个 100 ms,直接返回。
if (_tickCount == 0 && Math.Abs(currentMilliseconds - _startMilliSeconds) < 100)
{
return;
}
if (Math.Abs(currentMilliseconds - (_startMilliSeconds + (_tickCount + 1) * 1000)) <= 100)
{
_tickCount++;
if (_tickCount % IntervalSeconds == 0)
{
Elapsed?.Invoke(this, elapsedEventArgs);
}
}
}
public void Dispose()
{
_driveTimer?.Dispose();
}
}
}
最新文章
- 《C标准库》——之<;string.h>;
- UVa12092 Paint the Roads(最小费用最大流)
- ScriptManager.RegisterStartupScript
- SQLite.net发布后找不到";SQLite.Interop.dll";的问题
- 浅谈Redis数据库的键值设计(转)
- BestCoder Round #84 Aaronson
- 【Python】菜鸟的基本课程继续中
- HTTP协议理解
- python中去掉空行的问题
- Physiological Processes of Speech Production--Reading Notes (8)
- 基于visual Studio2013解决C语言竞赛题之0605strcat
- Android 程式开发:(廿一)消息传递 —— 21.3 使用Intent发送短信
- 创建和关联内容数据库到指定Web应用程序和站点集
- Jenkins环境集成第一弹
- idea为tomcat设置虚拟地址
- 1079. Total Sales of Supply Chain (25) -记录层的BFS改进
- Java异常处理最佳实践及陷阱防范
- object-fit、object-position 属性
- 2017-11-06 日语编程语言";抚子"; - 第三版特色初探
- stable