自从上次封装微秒延时函数后,利用空闲时间试着封装一个微秒定时器(类似MFC定时器形式)使用起来效果还不错。

关于定时器的几点介绍:
   1.设计采用了自动释放定时器节点方式(增加虚析构函数在内部做相关释放判断,即使用完不释放节点也没关系);
   2.设计采用了双向链表方式做定时器节点(为了方便起见,没有采用环形双向链表);
   3.增加了第三参数为回调函数(采用MFC风格,如果第三个参数不为空,超时后调用回调函数,否则调用默认函数);
   4.设计采用了并行方式(可以同时启动多个ID不相同的定时器,并且每个定时器之间没有影响);
   5.释放采用了先退出定时器线程,后删除节点风格(防止数据异常造成崩溃)。

函数定义如下

//参数一 定时器ID号,参数二 定时时间(微秒),参数三 回调函数(不需要设置NULL或者不写)
int TimeRun(int id,int outtime,void (CALLBACK* lpfnTimer)(/*HWND, UINT, UINT_PTR, DWORD*/) = NULL);//定时器启动函数//参数一 定时器ID号
void TestKillTimer(int id);//定时器销毁函数 (可以不使用)void CALLBACK Test123();//测试写的回调函数 函数名称及参数可以自己定 与定时器内以及定时器结构体的回调函数配套//第一个参数 定时器ID号(ID号用于多个定时器之间的判断)
void TestTime(int id);//测试用的普通定时器调用函数 想启动的函数写在这个函数内DWORD WINAPI TimerRunThread(LPVOID _this);//定时器线程函数typedef struct timest//定时器数据保存结构体
{int id;//ID号int outtime;//超时时间volatile int beginRun;//运行状态void (CALLBACK* lpfnTimer)(/*HWND, UINT, UINT_PTR, DWORD*/);//回调函数timest *prev,*next;//双向链表指针
}*ptimest;
typedef struct Testtimest//定时器执行结构体
{ptimest ptime,ptimehead;//定时器运行节点以及头节点Testtimest(){ptime = 0;ptimehead = 0;}virtual ~Testtimest()//析构函数内部封装了定时器对象退出后的检查及释放{while (0 != ptimehead){ptimest deletime;deletime = ptimehead->next;if (1 == ptimehead->beginRun)//如果定时线程还在执行 ,先退出线程再删除{ptimehead->beginRun = 0;UsSleep(ptimehead->outtime * 2);//删除线程节点前要留出当前定时器的2倍睡眠时间}delete ptimehead;ptimehead = deletime;}}
};
Testtimest testtime;

代码实现如下:

 int TimeRun(int id,int outtime,void (CALLBACK* lpfnTimer)(/*HWND, UINT, UINT_PTR, DWORD*/))//定时器启动实现 采用了可以多次重复创建并且删除的安全方式
{if (0 > id || 0 >= outtime){return -1;}testtime.ptime = testtime.ptimehead;//为方便多次删除后继续用,每次先获取首节点if (0 != testtime.ptime)//如果头节点不为空,判断当前新增定时器ID是否与之前增加ID重复{while (id != testtime.ptime->id && 0 != testtime.ptime->next)testtime.ptime = testtime.ptime->next;if (id == testtime.ptime->id)//如果启动的定时器Id与之前的重复 则不启动{return -1;}}if (0 == testtime.ptime){testtime.ptime = new timest;testtime.ptime->next = 0;testtime.ptime->prev = 0;testtime.ptimehead = testtime.ptime;}else{while (0 != testtime.ptime->next)testtime.ptime = testtime.ptime->next;testtime.ptime->next = new timest;testtime.ptime->next->next = 0;testtime.ptime->next->prev = testtime.ptime;}while (0 != testtime.ptime->next)testtime.ptime = testtime.ptime->next;testtime.ptime->id = id;//idtesttime.ptime->beginRun = 1;//启动状态testtime.ptime->outtime = outtime;//超时时间testtime.ptime->lpfnTimer = lpfnTimer;//回调函数HANDLE handle = CreateThread(NULL,0,TimerRunThread,testtime.ptime,0,NULL);CloseHandle(handle);//为了C程序也能运行采用了API线程,并且句柄没实际用处就直接释放掉return 0;
}void CALLBACK Test123()//测试回调函数实现
{int a;a = 2;
}DWORD WINAPI TimerRunThread(LPVOID _this)//定时器线程函数实现
{ptimest Runject = (/*decltype(_this)*/ptimest)_this;//本来想用获取类型方式来直接获取传入的类型,后来想到了在线程函数中类型是void*所以只能手动写入传入的参数类型while (1 == Runject->beginRun)//定时器状态为1执行,0时退出线程函数,删除定时器节点{UsSleep(Runject->outtime);if (0 != Runject->lpfnTimer)//如果回调函数不为空调用回调函数{Runject->lpfnTimer();}else{TestTime(Runject->id);//根据ID号进行调用普通定时器启动函数}}return 0;
}void TestTime(int id)//测试 定时器调用函数实现
{int a = 0;if (1 == id){a = 1;}if (2 == id){a = 2;}if (3 == id){a = 3;}
}
void TestKillTimer(int id)//定时器销毁函数实现
{ptimest deletime = testtime.ptimehead;ptimest next,prev;if (id == deletime->id)//首节点{next = testtime.ptimehead->next;deletime->beginRun = 0;UsSleep(deletime->outtime * 2);//为了可以退出定时器线程并且安全删除定时器节点采用了2倍超时时间delete deletime;deletime = 0;testtime.ptimehead = next;if (0 != next){next->prev = 0;}return ;}while (id != deletime->id && 0 != deletime)deletime = deletime->next;if (0 == deletime)//没有找到Id{return ;}prev = deletime->prev;next = deletime->next;deletime->beginRun = 0;UsSleep(deletime->outtime * 2);delete deletime;deletime = 0;prev->next = next;if (0 != next){next->prev = prev;}
}int UsSleep(int us)//微秒延时函数实现
{LARGE_INTEGER fre;if (QueryPerformanceFrequency(&fre)){LARGE_INTEGER run,priv,curr,res;run.QuadPart = fre.QuadPart * us / 1000000;QueryPerformanceCounter(&priv);do {QueryPerformanceCounter(&curr);} while (curr.QuadPart - priv.QuadPart < run.QuadPart);curr.QuadPart -= priv.QuadPart;int nres = (curr.QuadPart * 1000000 / fre.QuadPart);return nres;}return -1;//
}

使用方式:

TimeRun(1,500,NULL);
TimeRun(2,1000,Test123);
TestKillTimer(1);
//TestKillTimer(2);

关于微秒级延时函数详细介绍参考:http://blog.csdn.net/a29562268/article/details/68955533!

Windows高精度微秒级(并发)定时器实现相关推荐

  1. c#实现 微秒级定时器,高精度定时器

    c# 微秒级定时器,高精度定时器 整个代码,封装成类 using System; using System.Runtime.InteropServices;namespace winTest {/// ...

  2. windows下实现微秒级的延时

    1.微秒级的延时肯定不能基于消息(SetTimer函数),因为一出现消息堵塞等就会影响精 度,而且setTimer单位才是毫秒.实际响应时间可能要到55毫秒左右. 2.微秒级的延时也不能不能基于中断, ...

  3. Windows微秒级定时方法

    在做硬件相关的程序时,需要大量的数据传输,当数据发送量大于设备接口接收量时会造成字节bit位覆盖的问题(比如单根串口线每次发送或者接收一个bit如果发送速度大于接收速度会造成前一个bit位被下一个bi ...

  4. 无需另配定时器在STM32 HAL下实现微秒级延时(兼容FreeRTOS)

    目录 前言 一.代码部分 二.使用和验证 1.引入头文件 2.初始化 3.使用和验证 三.可移植性 总结 前言 接触HAL库差不多两年了,一直苦于HAL库没有自带微秒级的延时,网上的前辈们给出的解决方 ...

  5. PHP uniqid()函数可用于生成不重复的唯一标识符,该函数基于微秒级当前时间戳。在高并发或者间隔时长极短(如循环代码)的情况下,会出现大量重复数据。即使使用了第二个参数,也会重复,最好的方案是结

    转载地址:http://www.51-n.com/t-4264-1-1.html PHP uniqid()函数可用于生成不重复的唯一标识符,该函数基于微秒级当前时间戳.在高并发或者间隔时长极短(如循环 ...

  6. Linux下的微秒级定时器: usleep, nanosleep, select, pselect

    Linux下的微秒级定时器: usleep, nanosleep, select, pselect 标签: linuxnulldelaystructdate 2012-02-07 23:29 4979 ...

  7. Windows 微秒级 延时

    QueryPerformanceCounter()这个函数返回高精确度性能计数器的值,它可以以微妙为单位计时. // 微秒级延时 参数: 微秒 void Control::MySleep(DWORD ...

  8. TIM微秒级计时学习笔记

    TIM微秒级计时学习笔记 前言 使用工具 TIM基本定时器的使用步骤 前言 最近需要写一个微秒级的计时器,查了一圈,发现基本是毫秒级的计时器,如: HAL库中的HAL_GetTick(); C语言中的 ...

  9. C++11的chrono库,可实现毫秒微秒级定时

    C++11有了chrono库,可以很容易的实现定时功能. chrono: chrono库主要包含了三种类型:时间间隔Duration.时钟Clocks和时间点Time point. Duration: ...

最新文章

  1. 【Java】排序算法 之 【归并排序】 总结
  2. python程序设计试卷_2013Python程序设计期末试卷A
  3. VTK:重新采样附加的 PolyData用法实战
  4. boost::coroutine2模块实现协程的测试程序
  5. P3312 [SDOI2014]数表(离线 + 树状数组前缀和优化)
  6. 让WebStorm支持dojo的智能提示
  7. spine纹理解包 黑底_本期全欧美阵容!种草了艾玛罗的斑马纹,海狸的针织Bra【海报街拍】...
  8. SQL SERVER 高效存储过程分页(Max/Min方法)
  9. Retrofit的初次使用
  10. SQL语句的执行计划
  11. 博微软件网络服务器安装,负载均衡服务器nginx详细安装教程及网络部署
  12. c语言常量(c语言常量定义规则)
  13. SSRF利用 Gopher |Gopher攻击mysql及内网
  14. 机器学习神器Scikit-Learn保姆级入门教程
  15. 【Visual C 】游戏开发笔记三十四 浅墨DirectX提高班之三 起承转合的艺术 Direct3D渲染五步曲
  16. py使用bar绘制堆积/带误差棒柱形图
  17. css设置全局内边距为0,重置CSS - 将填充和边距设置为0?
  18. 名帖131 梁诗正 小楷《谢恩折》
  19. 认知服务调用如何使用图片的DataURL
  20. Matlab最小面积包围四边形

热门文章

  1. 造了一个 Redis 分布锁的轮子,没想到还学到这么多东西!!!
  2. 山哥新作:架构师必备技能之业务分析
  3. DevOps是什么意思
  4. Spring Cloud 入门 之 Zuul 篇(五)
  5. maven导出项目依赖的jar包
  6. JEECG常见问题大全征集
  7. abap 优化之ST05
  8. 企业网络之间资源互访
  9. Spring4 MVC HelloWorld 注解和JavaConfig实例
  10. 关于ActiveMQ序列化对象爆“Forbidden class xxx! ...”问题的解决