C# 消除累计误差的倒计时
使用 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# 消除累计误差的倒计时的更多相关文章
- 玩转X-CTR100 l STM32F4 l 电机正交编码器
我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器的电机正交编码器,X- ...
- 微信小程序中利用时间选择器和js无计算实现定时器(将字符串或秒数转换成倒计时)
转载注明出处 改成了一个单独的js文件,并修改代码增加了通用性,点击这里查看 今天写小程序,有一个需求就是用户选择时间,然后我这边就要开始倒计时. 因为小程序的限制,所以直接选用时间选择器作为选择定时 ...
- Android开发案例 – 在AbsListView中使用倒计时
在App中, 有多种多样的倒计时需求, 比如: 在单View上, 使用倒计时, 如(如图-1) 在ListView(或者GridView)的ItemView上, 使用倒计时(如图-2) 图-1 图-2 ...
- JS案例之3——倒计时
利用简单的数字累加循环模拟倒计时的效果,逻辑比较简单.如果大牛们有更好的办法欢迎补充. 这种效果经常用于在规定的时间做某件事.比如在1分钟之后重新发送验证码等. 案例演示: 源代码如下: <!D ...
- Linux环境下shell和vim中乱码原因及消除办法
shell和vim中乱码原因及消除办法 作者:Jack47 在Linux下开发,经常遇到乱码问题:shell或者vim中显示不了中文,或者能够显示,但不能输入中文.每次都是上网去搜,或者同事告诉我一些 ...
- js倒计时-倒计输入的时间
计算指定时间到指定时间之间相差多少天.时.分.秒. 节日.活动.商城常用. 原理: 主要使用到时间戳,也就是从1970 年 1 月 1 日 到指定时间的毫秒数. 1. 求出毫秒差 :当两个时间直接进行 ...
- 微信小程序定时器组件(输入时间字符串即可倒计时)
昨天写了代码,今天发现要重用,干脆就抽出来做个组件得了,顺便还改善了一下代码通用性. 昨天的代码在这里 github下载地址 用法: 引入: var timer = require('../../pl ...
- Linq to sql 有什么办法可以实现消除列重复?
比如数据库里有一表,有两个字段:ID User1 小白2 小红3 小白 过滤User列为小白的重复项后,我想要得到:ID User1 小白2 小红 如果写db.linq.customer.Distin ...
- jQuery获取短信验证码+倒计时实现
jQuery 短信验证码倒计时 <script type="text/javascript" charset="utf-8"> $(function ...
随机推荐
- 2017北京国庆刷题Day4 afternoon
期望得分:100+100+0=200 实际得分:5+0+0=5 每加入一个数,x的因数位置++ 注意:根号x枚举时,如果x是完全平方数,根号x会重复累计2次,要减去 考场上没减,5分 /(ㄒoㄒ)/~ ...
- HTML入门(三)后台系统显示页面_框架标签
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- JAVA中反射机制二
声明:如需转载请说明地址来源:http://www.cnblogs.com/pony1223 反射二 利用反射创建对象 1.利用反射创建对象,首先我们创建一个类,类里面,我们知道构造函数有默认的构造函 ...
- [数据库中间件]centos6.6下配置libzdb所产生的错误
1.关于gmtime_r.timegm的隐藏声明错误,从系统的time.h中复制两个函数引用到libzdb自己定义的time.h,代码如下: extern struct tm *gmtime_r (c ...
- javascript操作对象的方法
with 确定某个对象的作用区域,在with代码段内的次对象的属性或方法可以直接使用. 例: //比如stu中有name,age属性和walk方法 with(stu) { alert(name+&qu ...
- Xcode下 gdb 调试命令
Xcode的调试器为用户提供了一个GDB的图形化界面,GDB是GNU组织的开放源代码调试器.您可以在Xcode的图形界面里做任何事情:但是,如果您需要您可以在命令行里使用GDB的命令,且gdb可以在终 ...
- Codeforces 870E Points, Lines and Ready-made Titles 计数
题目链接 题意 给定二维坐标上的\(n\)个点,过每个点可以 画一条水平线 或 画一条竖直线 或 什么都不画,并且若干条重合的直线被看做同一条.问共可能得到多少幅不同的画面? 题解 官方题解 仆の瞎扯 ...
- weblogic nmap扫描脚本
CVE-2018-2894 / Nmap利用脚本,可批量批量快速扫描getshell.检测漏洞.利用漏洞 地址:https://github.com/Rvn0xsy/nse_vuln/tree/ma ...
- udhcpc命令
要使用网络通讯,所以不可避免的要用到dhcp.理想的网络通讯方式是下面3种都要支持: 1,接入已有网络.这便要求可以作为dhcp客户端. 2,作为DHCP服务器,动态分配IP. 简单说下前2种情况. ...
- python从2.6.x升级到2.7.x
[前提] 今日是20171207,目前Linux发行版默认安装的Python版本都是2.6.x,但是这个版本Python已经不再进行维护了. 所以需要将Python做一个升级,到2.7.x [注意] ...