C++ Timer
Timer机制
这里所说的Timer机制是定时器(Timer),例如在Javascript中就提供定时执行代码的功能。但是在C++标准中暂时没有实现这一功能的函数。
Javascript中的Timer
Javascript用来处理延时和定时任务的setTimeOut和setInterval函数应用非常广泛,它们都用来处理延时和定时任务,比如打开网页一段时间后弹出一个登录框,页面每隔一段时间发送异步请求获取最新数据等等。但它们的应用是有区别的。
setTimeout
setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用clearInterval来取消这个定时器。setTimeout只执行一次。
var timeId=setTimeout(func|code,delay) //间隔delay毫秒执行函数func或者code
比如下面这段代码:
console.log('First');
setTimeout('console.log('Second')',1000);
console.log('Third');
的执行结果是先打印出"First与Third",然后再1000ms之后打印出"Second"。
而在传入函数的时候,我们还可以增加参数:
setTimeout(function(a,b,c){console.log(a+b);console.log(c);},1000,1,1,5);
此外,如果被setTimeout推迟执行的回调函数是某个对象的方法,那么用到的this关键字将指向全局环境:
var x = 1;var o = {x: 2,y: function(){console.log(this.x);}};setTimeout(o.y,1000);
执行结果x的值为1而不是定义的对象o中的2!
给出一个实际中使用的小例子:
function User(login) {
this.login = login;
this.sayHi = function()
{console.log("Hello "+this.login);}
}
var user = new User('John');
setTimeout(function() {user.sayHi();}, 1000);
setTimeout这里调用的为function(){user.sayHi()};
,因为如果执行user.sayHi,他会再全局对象中执行,this.login取不到值。
setInterval
setInterval函数的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。对应的取消函数为clearInterval
运行机制
setTimeout和setInterval的运行机制是,将指定的代码移出本次执行,等到下一轮Event Loop时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮Event Loop时重新判断。这意味着,setTimeout指定的代码,必须等到本次执行的所有代码都执行完,才会执行。
每一轮Event Loop时,都会将“任务队列”中需要执行的任务,一次执行完。setTimeout和setInterval都是把任务添加到“任务队列”的尾部。因此,它们实际上要等到当前脚本的所有同步任务执行完,然后再等到本次Event Loop的“任务队列”的所有任务执行完,才会开始执行。由于前面的任务到底需要多少时间执行完,是不确定的,所以没有办法保证,setTimeout和setInterval指定的任务,一定会按照预定时间执行。
比如说我用了setTimeout延迟了一个函数1000ms后执行,但是我代码后面存在耗时超过1000ms的执行代码,那么我利用setTimeout延迟的函数必须等到耗时很长的代码执行完成后才能轮到它执行。这一点会造成一种"累积触发"的现象,假如是使用setInterval,存在上述耗时很长的代码,那么setInterval的函数会排队并逐渐被累积起来,等到前面的代码执行完成会一股脑的连续触发。
C++ Timer
一个非常简单的库
这个是由shalithasuranga写的非常简易的timer
我们将代码贴在下面:
main.cpp:
#include <iostream>
#include "timercpp.h"
using namespace std;
int main() {
Timer t = Timer();
t.setInterval([&]() {
cout << "Hey.. After each 1s..." << endl;
}, 1000);
t.setTimeout([&]() {
cout << "Hey.. After 5.2s. But I will stop the timer!" << endl;
t.stop();
}, 5200);
cout << "I am Timer" <<endl;
while(true); // Keep mail thread active
}
timercpp.h:
#include <iostream>
#include <thread>
#include <chrono>
class Timer {
bool clear = false;
public:
void setTimeout(auto function, int delay);
void setInterval(auto function, int interval);
void stop();
};
void Timer::setTimeout(auto function, int delay) {
this->clear = false;
std::thread t([=]() {
if(this->clear) return;
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
if(this->clear) return;
function();
});
t.detach();
}
void Timer::setInterval(auto function, int interval) {
this->clear = false;
std::thread t([=]() {
while(true) {
if(this->clear) return;
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
if(this->clear) return;
function();
}
});
t.detach();
}
void Timer::stop() {
this->clear = true;
}
首先看一下main函数,调用了两个接口setTimeout与setInterval函数,两个函数是lambda表达式(捕捉引用符号)。其实就是一个简单的测试接口函数。
下面再谈一谈Timer的接口,首先auto的写法适用于C++20,为了符合众多编译器,我们可以改成模板形式:
#include <iostream>
#include <thread>
#include <chrono>
class Timer {
bool clear = false;
public:
template<typename T>
void setTimeout(T function, int delay);
template<typename T>
void setInterval(T function, int interval);
void stop();
};
template<typename T>
void Timer::setTimeout(T function, int delay) {
this->clear = false;
std::thread t([=]() {
if (this->clear) return;
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
if (this->clear) return;
function();
});
t.detach();
}
template<typename T>
void Timer::setInterval(T function, int interval) {
this->clear = false;
std::thread t([=]() {
while (true) {
if (this->clear) return;
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
if (this->clear) return;
function();
}
});
t.detach();
}
void Timer::stop() {
this->clear = true;
}
在Timer类中定义了一个clear变量,是用来表示计时器是否应该停止的变量。然后出现了std::thread t([=])
,这个lambda函数用来判断计时器是否应该停止,如果停止了就立刻返回。然后调用了std::this_thread::sleep_for
用来休眠线程,可以参看这个.功能为阻塞当前线程执行,至少经过指定的 sleep_duration
。此函数可能阻塞长于 sleep_duration
,因为调度或资源争议延迟。
我们分离:t.detach()
,从 thread 对象分离执行的线程,允许执行独立地持续。一旦线程退出,则释放所有分配的资源。
Boost Asio
再有就是Boost库了,但是这个库过于庞大,有兴趣的可以去看一看:Boost Asio
C++ Timer的更多相关文章
- C# - 计时器Timer
System.Timers.Timer 服务器计时器,允许指定在应用程序中引发事件的重复时间间隔. using System.Timers: // 在应用程序中生成定期事件 public class ...
- winform 用户控件、 动态创建添加控件、timer控件、控件联动
用户控件: 相当于自定义的一个panel 里面可以放各种其他控件,并可以在后台一下调用整个此自定义控件. 使用方法:在项目上右键.添加.用户控件,之后用户控件的编辑与普通容器控件类似.如果要在后台往窗 ...
- 【WPF】 Timer与 dispatcherTimer 在wpf中你应该用哪个?
源:Roboby 1.timer或重复生成timer事件,dispatchertimer是集成到队列中的一个时钟.2.dispatchertimer更适合在wpf中访问UI线程上的元素 3.Dispa ...
- STM32F10xxx 之 System tick Timer(SYSTICK Timer)
背景 研究STM32F10xxx定时器的时候,无意间看到了System tick Timer,于是比较深入的了解下,在此做个记录. 正文 System tick Timer是Cotex-M内核的24位 ...
- 本地数据Store。Cookie,Session,Cache的理解。Timer类主要用于定时性、周期性任务 的触发。刷新Store,Panel
本地数据Store var monthStore = Ext.create('Ext.data.Store', { storeId : 'monthStore', autoLoad : false, ...
- WinForm用户控件、动态创建添加控件、timer控件--2016年12月12日
好文要顶 关注我 收藏该文 徐淳 关注 - 1 粉丝 - 3 0 0 用户控件: 通过布局将多个控件整合为一个控件,根据自己的需要进行修改,可对用户控件内的所有控件及控件属性进行修 ...
- java Timer 定时每天凌晨1点执行任务
import java.util.TimerTask;/** * 执行内容 * @author admin_Hzw * */public class Task extends TimerTask { ...
- [C#].NET中几种Timer的使用
这篇博客将梳理一下.NET中4个Timer类,及其用法. 1. System.Threading.Timer public Timer(TimerCallback callback, object s ...
- 使用系统自带的GCD的timer倒计时模板语句遇到的小坑。。
今天折腾了下系统gcd的 但是如果不调用这句dispatch_source_cancel()那么这个timer根本不工作....解决方法如下: 实现一个倒计时用自带的gcd如此简洁.. 原因可能是如果 ...
- C# 定时器 Timers.Timer Forms.Timer
1.定义在System.Windows.Forms里 Windows.Forms里面的定时器比较简单,只要把工具箱中的Timer控件拖到窗体上,然后设置一下事件和间隔时间等属性就可以了 //启动定时器 ...
随机推荐
- error:crosses initialization of ...的解决办法
switch(c) { case 0x01: int temp = a + b; .... break; case 0x02: break; default:break; } 此时会报如题所示错误 原 ...
- Linux xclip命令
一.简介 xclip命令建立了终端和剪切板之间通道,可以用于以命令的方式将终端输出或文件的内容保存到剪切板中,也可以用于将剪切板的内容输出到终端或文件中. 在 X 系统里面,从一个窗口复制一段文字到另 ...
- scala _ parameter
Given that sequence, use reduceLeft to determine different properties about the collection. The foll ...
- Shiro——认证概述
认证流程 身份认证流程 首先调用 Subject.login(token) 进行登录,其会自动委托给SecurityManager SecurityManager 负责真正的身份验证逻辑:它会委托给A ...
- WCF把书读薄(3)——数据契约、消息契约与错误契约
上一篇:WCF把书读薄(2)——消息交换.服务实例.会话与并发 十二.数据契约 在实际应用当中数据不可能仅仅是以int Add(int num1, int num2)这种简单的几个int的方式进行传输 ...
- Python基础入门-集合
今天给大家分享的是python中集合(set)的概念,集合这个词其实和高中学的数学集合的概念很相近,或者作为初学者你就可以把它理解为数学当中的集合.在python中集合(set)是由一个个键组成的,但 ...
- 时间日期控件的处理-Selenium
很多人问时间日期的空间怎么处理,但是时间日期控件各种各样,你可能遇到正常点的像这样: 当然也可能遇到难点的,像这样: 当然,也不排除会遇到变态的,像这样: 呵呵,真要一个个想着怎么去选择,简直是非人类 ...
- Model View Controller (MVC) Overview
By Rakesh Chavda on Jul 01, 2015 What is MVC?Model View Controller is a type of user interface archi ...
- (转)使用Jquery+EasyUI 进行框架项目开发案例讲解之四---组织机构管理源码分享
原文地址:http://www.cnblogs.com/huyong/p/3404647.html 在上三篇文章 <使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码 ...
- string Format转义大括号
String.Format("{0} world!","hello") //将输出 hello world!,没有问题,但是只要在第一个参数的任意位置加上一个大 ...