使用 c++ 在 windows 上稳定定时执行一个函数

这篇具有很好参考价值的文章主要介绍了使用 c++ 在 windows 上稳定定时执行一个函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

#include <iostream>
#include <Windows.h>
#include <thread>
#pragma comment( lib, "Winmm" )

static int counter = 0;
static int64_t ticks_per_second;
void __stdcall on_timer(HWND h, UINT ui, UINT_PTR up, DWORD dw)
{
    std::cout << "time out, counter=" << counter << std::endl;
    counter = 0;
}
void get_message_trd_func()
{
    SetTimer(NULL, 0, 1000, on_timer);
    MSG msg;
    while (GetMessageA(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageA(&msg);
    }
}
int main()
{
    std::cout << "go!" << std::endl;
    timeBeginPeriod(1);
    QueryPerformanceFrequency((LARGE_INTEGER*)&ticks_per_second);
    const double expected = 1.0 / 60.0;
    const int64_t expected_ticks = (int64_t)(expected * ticks_per_second);

    std::thread thr(get_message_trd_func);
    for (;;)
    {
        int64_t before_ticks = 0;
        QueryPerformanceCounter((LARGE_INTEGER*)&before_ticks);

        // do something...
        for (int i = 0; i < 10000; i++)
        {
            float a = i * i + i + sin(i) + sqrt(i);
        }

        int64_t after_ticks = 0;
        QueryPerformanceCounter((LARGE_INTEGER*)&after_ticks);
        counter++;

        int64_t ticks_need_sleep = expected_ticks - (after_ticks - before_ticks);

        double ms_need_sleep = (double)ticks_need_sleep / ticks_per_second * 1000.0;
        if (ms_need_sleep >= 1.0)
            Sleep((DWORD)ms_need_sleep);
        else
            continue;
    }
}

这里主要用到的几个 win32api 为

  • MMRESULT timeBeginPeriod
    使用该 api 需要链接 Winmm, 所以我们在文件顶部加入#pragma comment( lib, "Winmm" ).
    它的作用是请求提高一些计时器的精度比如这里的Sleep, 默认 windows 似乎只会给我们提供 10ms 左右很粗糙的精度, 所以这里我们直接请求尽可能的高的精度, 即 1ms.

  • QueryPerformanceFrequency
    该 api 用于获取"性能计时器"的精度, 单位是 ticks每秒. 在我的机子上它的值是 10000000, 可以看到精度还是很令人满意的. 在这里我们将其与expected(也就是期望每次调用的间隔,单位s)进行相乘, 得到一个以ticks为单位的间隔.

  • QueryPerformanceCounter
    该 api 会检测"性能计时器"的值, 单位为 ticks, 在 msdn 中其精度的描述为 <1us.

那么结合上述几个 api 以及几个简单的数学运算, 这样就可以相对稳定的定时调用函数了(在这里是 1s 60 次):

time out, counter=59
time out, counter=59
time out, counter=60
time out, counter=59
time out, counter=58
time out, counter=60

当你注释掉timeBeginPeriod的调用后你会发现结果不是很乐观(即使我们期望 1s 调用 60 次):

time out, counter=33
time out, counter=31
time out, counter=32
time out, counter=31

最后, 这个可能常见于游戏的帧率控制, 实际上我就是从这里知道的这些东西(x文章来源地址https://www.toymoban.com/news/detail-588321.html

到了这里,关于使用 c++ 在 windows 上稳定定时执行一个函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Windows环境下通过 系统定时 执行脚本方式 压缩并备份文件夹 到其他数据盘

    压缩时需要使用7-zip进行调用,因此根据自己电脑进行安装 官网:https://www.7-zip.org/ 新建记事本文件,重命名为git_back_up.bat 注意:如果不设置可能会导致定时任务无法执行 开“控制面板-管理工具-本地安全策略”,选择“安全设置-本地策略-安全选项”,在右边列表中找到“

    2024年02月14日
    浏览(56)
  • 【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值

     [导读]本系列博文内容链接如下: 【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 【C++】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C++】做一个飞

    2024年02月15日
    浏览(35)
  • Python 跨文件调用函数 + 在一个文件中执行另一个文件

    在很多时候,为了保持代码与代码文件的简洁和逻辑清晰,通常会将许多相类似的函数放在一个文件中,在一个 main.py 中去调用它们。调用 Python 函数的时候,大致会存在如下几种情况。 假如现在有这样一个文件树(从其他地方copy的,稍加整改) 文件内容如下: 为什么要有

    2024年02月02日
    浏览(54)
  • Crontab(定时任务)使用: Linux-Centos7使用crontab制定定时任务,定时执行某任务

    参考:https://blog.csdn.net/m0_49605975/article/details/120701771 1.用yum命令安装Crontab 2.启动,关闭,重启 3.设置开机启动 1.设置定时任务-进入编辑模式 -和vim操作一至 2.查看定时任务列表 3.添加定时任务 样例: 添加一个定时任务,定时清空某个文件夹里面日志文件的内容 3.1 编写一个清

    2024年02月01日
    浏览(72)
  • C++执行程序计时函数详解

    通常计时函数主要有两个,分别是getTickCount()和getTickFrequency(). getTickCount()函数,返回的是CPU自某个时间(如启动电脑)以来走过的时钟周期数; getTickFrequency()函数,返回的是CPU一秒钟所走的时钟周期数,这样我们就可以轻松的以秒为单位对某运算进行计时; 将两个函数组合

    2024年02月13日
    浏览(47)
  • javascript:在foreach循环完成之后执行一个回调函数

    常规方法 代码如下面demo所示,在foreach的回调函数中进行判断,当循环到数组最后一位元素的时候,执行回调函数: 使用Promise实现 实际工作中,当目标数组的元素内容比较复杂,在回调函数中没有办法进行简单的逻辑判断时,可以使用Promise.all 方法实现:

    2024年02月11日
    浏览(45)
  • Linux 环境使用定时任务执行shell脚本

    前言:Linux添加定时任务需要依赖crond服务,如果没有该服务,需要先安装:yum -y install crontabs 1、crond服务相关命令介绍         启动crond服务: service crond start         停止crond服务: service crond stop         重启crond服务: service crond restart         重载crond服务

    2024年02月16日
    浏览(63)
  • 使用shedlock实现分布式定时任务锁【防止task定时任务重复执行】

    第一步:引入shedlock相关依赖 ShedLock还可以使用Mongo,Redis,Hazelcast,ZooKeeper等外部存储进行协调,例如使用redis则引入下面的包 第二步:创建数据库表结构,数据库表的脚本如下: 第三步:添加shedlock配置类 (定时任务防重复执行的配置类) 第四步:在启动类上添加启动注

    2024年02月10日
    浏览(41)
  • Windows10使用Xrdp远程桌面连接Ubuntu主机【不稳定】

    Ubuntu 服务器通常使用命令行进行管理,并且默认没有安装桌面环境。如果你正在运行 Ubuntu 桌面版,忽略这一步。 在 Ubuntu 源仓库有很多桌面环境供你选择。一个选择是安装 Gnome,它是 Ubuntu 20.04 的默认桌面环境。另外一个选项就是安装 xfce。它是快速,稳定,并且轻量的桌面

    2024年02月06日
    浏览(50)
  • 运维Shell脚本小试牛刀(七):在函数文脚本件中调用另外一个脚本文件中函数|函数递归调用|函数后台执行

    运维Shell脚本小试牛刀(一) 运维Shell脚本小试牛刀(二) 运维Shell脚本小试牛刀(三)::$(cd $(dirname $0); pwd)命令详解 运维Shell脚本小试牛刀(四): 多层嵌套if...elif...elif....else fi_蜗牛杨哥的博客-CSDN博客 Cenos7安装小火车程序动画 运维Shell脚本小试牛刀(五):until循环 运维Shell脚本小试牛刀

    2024年02月09日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包