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控件拖到窗体上,然后设置一下事件和间隔时间等属性就可以了 //启动定时器 ...
随机推荐
- Leetcode:ZigZag Conversion分析和实现
问题的大意就是将字符串中的字符按锯齿状(倒N形)垂直由上向下放置,最后水平从左向右读取.比如 ABCDEFGHIJKLMN,4表示 A G M B F H ...
- 2014蓝桥杯B组初赛试题《六角填数》
题目描述: 如图[1.png]所示六角形中,填入1~12的数字. 使得每条直线上的数字之和都相同. 图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少? 请通过浏览器提交 ...
- sencha警告:[WARN][Anonymous] [Ext.Loader] Synchronously loading 'Ext.field.Text'
chrome开发者工具下提示: [WARN][Anonymous] [Ext.Loader] Synchronously loading 'Ext.field.Text'; consider addi ...
- HTML中meta标签的作用与使用
META标签用来描述一个HTML网页文档的属性 META标签可分为两大部分:HTTP-EQUIV和NAME变量. HTTP实例 HTML代码实例中有一项内容是 <meta http-equiv= ...
- Struts中ActionContext和ServletActionContext的比较
一.ActionContext在Struts2开发中除了将请求参数自动设置到Action的字段中,往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息,甚至需要直 ...
- VS2013中全局属性与局部属性的设置
为了更好的体现程序与库的独立性,vc++2013 中库路径设置不再采用全局设置,就是说在每个工程中都可以有自己独立的库路径设置,当然你如果不设置,那默认就是vs2013自己的库路径.但是如果你需要用到 ...
- 2.python IP/DNS地址处理之IPy/Dnspython模块
1.IPy模块 在IP地址规划中,涉及到计算大量的IP地址,包括网段.网络掩码.广播地址.子网数.IP类型等,即便是专业的网络人员也要进行繁琐的计算,而IPy模块提供了专门针对IPV4地址与IPV6 ...
- linux 查看 PHP 的默认版本。
命令 env env:显示当前用户的环境变量: which php
- svn下载安装
TortoiseSVN 下载地址:http://subversion.apache.org/packages.html#windows VisualSVN Server 下载地址:https://ww ...
- C#设计模式系列:适配器模式(Adapter Pattern)
一.引言 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用.但是新环境要求的接口是这些现存对象所不满足的.如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同 ...