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的更多相关文章

  1. C# - 计时器Timer

    System.Timers.Timer 服务器计时器,允许指定在应用程序中引发事件的重复时间间隔. using System.Timers: // 在应用程序中生成定期事件 public class ...

  2. winform 用户控件、 动态创建添加控件、timer控件、控件联动

    用户控件: 相当于自定义的一个panel 里面可以放各种其他控件,并可以在后台一下调用整个此自定义控件. 使用方法:在项目上右键.添加.用户控件,之后用户控件的编辑与普通容器控件类似.如果要在后台往窗 ...

  3. 【WPF】 Timer与 dispatcherTimer 在wpf中你应该用哪个?

    源:Roboby 1.timer或重复生成timer事件,dispatchertimer是集成到队列中的一个时钟.2.dispatchertimer更适合在wpf中访问UI线程上的元素 3.Dispa ...

  4. STM32F10xxx 之 System tick Timer(SYSTICK Timer)

    背景 研究STM32F10xxx定时器的时候,无意间看到了System tick Timer,于是比较深入的了解下,在此做个记录. 正文 System tick Timer是Cotex-M内核的24位 ...

  5. 本地数据Store。Cookie,Session,Cache的理解。Timer类主要用于定时性、周期性任务 的触发。刷新Store,Panel

    本地数据Store var monthStore = Ext.create('Ext.data.Store', { storeId : 'monthStore', autoLoad : false, ...

  6. WinForm用户控件、动态创建添加控件、timer控件--2016年12月12日

    好文要顶 关注我 收藏该文 徐淳 关注 - 1 粉丝 - 3       0 0     用户控件: 通过布局将多个控件整合为一个控件,根据自己的需要进行修改,可对用户控件内的所有控件及控件属性进行修 ...

  7. java Timer 定时每天凌晨1点执行任务

    import java.util.TimerTask;/** * 执行内容 * @author admin_Hzw * */public class Task extends TimerTask {  ...

  8. [C#].NET中几种Timer的使用

    这篇博客将梳理一下.NET中4个Timer类,及其用法. 1. System.Threading.Timer public Timer(TimerCallback callback, object s ...

  9. 使用系统自带的GCD的timer倒计时模板语句遇到的小坑。。

    今天折腾了下系统gcd的 但是如果不调用这句dispatch_source_cancel()那么这个timer根本不工作....解决方法如下: 实现一个倒计时用自带的gcd如此简洁.. 原因可能是如果 ...

  10. C# 定时器 Timers.Timer Forms.Timer

    1.定义在System.Windows.Forms里 Windows.Forms里面的定时器比较简单,只要把工具箱中的Timer控件拖到窗体上,然后设置一下事件和间隔时间等属性就可以了 //启动定时器 ...

随机推荐

  1. 相关度算法BM25

    BM25算法,通常用来作搜索相关性平分.一句话概况其主要思想:对Query进行语素解析,生成语素qi:然后,对于每个搜索结果D,计算每个语素qi与D的相关性得分,最后,将qi相对于D的相关性得分进行加 ...

  2. 图论算法》关于tarjan算法两三事

    关于tarjan,在下觉得这个算法从本质上是一种暴力求强连通分量的方法,但事实上这也是最有效的求强连通分量的方法之一,它对于处理各种强连通分量中奇怪问题,都可以直接转化,所以比较通用和常见. 什么是t ...

  3. css四可见,部分可见和重叠半透明

    <html> <head> <title>javascript</title> <style type="text/css"& ...

  4. logistic growth model . 求解方法 (高斯牛顿法)

    https://www.stat.tamu.edu/~jnewton/604/chap4.pdf http://www.metla.fi/silvafennica/full/sf33/sf334327 ...

  5. AIO和NIO的理解

    AIO: AIO 背后的基本思想是允许进程发起很多 I/O 操作,而不用阻塞或等待任何操作完成,可以继续做 另外的事情,等I/O操作完成,内核会通过函数回调或者信号机制通知用户进程.这样很大程度提高了 ...

  6. Asp.Net程序目录下文件夹或文件操作导致Session失效的解决方案

    1.配置web.config <system.web> <sessionState mode="StateServer" stateConnectionStrin ...

  7. C# 关于接口与基类的理解(二者的区别)

    接口(接口的名称一般用大写字母I开头的)是把公共实例(非静态)方法和属性组合起来,以封装特定功能的一个集合.(其实,接口简单理解就是一种约定,使得实现接口的类或结构在形式上保持一致) 注意:使用接口可 ...

  8. css总结16:HTML5 多媒体音频(Audio)视频(video )

    1 显示嵌入网页中的 MP3 文件: <embed height="50" width="100" src="horse.mp3"&g ...

  9. 对request,session,application作用域形象理解

    看到一篇比较有意思的文章,分享一下.原网址:http://blog.csdn.net/rushkid02/article/details/8063792 几乎所有的Web开发语言都支持Session功 ...

  10. Android ViewPager + Fragment的布局

    ViewPager And Fragment 1.之前有篇博客是讲ViewPager的用法的:http://www.cnblogs.com/liangstudyhome/p/3773156.html ...