每1秒调用一个函数(精确) 我正在研究一个简单的C++游戏模拟程序,有一个UpDeDeO()函数更新游戏的当前状态,它必须精确地每隔1秒调用一次。如果我使用这样的循环: while(//some condition) { update(); Sleep(1000); } void update(); //your update void UpdateAsync() // the async update { std::thread([]() { update(); }).detach(); }

每1秒调用一个函数(精确) 我正在研究一个简单的C++游戏模拟程序,有一个UpDeDeO()函数更新游戏的当前状态,它必须精确地每隔1秒调用一次。如果我使用这样的循环: while(//some condition) { update(); Sleep(1000); } void update(); //your update void UpdateAsync() // the async update { std::thread([]() { update(); }).detach(); },c++,multithreading,asynchronous,delay,sleep,C++,Multithreading,Asynchronous,Delay,Sleep,那么函数将不会每隔1秒调用一次,而是每隔(1+update()的执行时间)调用一次。 我读过各种解决方案,比如异步函数、多线程,或者使用std::chrono计算函数的执行时间,然后从1000ms参数中减去它以进入睡眠状态。其中一些对于我的简单案例来说太复杂了,如果我不能很好地理解它们,那么使用其他一些似乎是不安全的 有人能告诉我什么是适合我的要求的解决方案吗? 提前感谢。您可以避免使用chrono来替代这个更简单的选项。然而,如果您想要μs-ns精度,我强烈建议使用chrono #includ

那么函数将不会每隔1秒调用一次,而是每隔(1+update()的执行时间)调用一次。 我读过各种解决方案,比如异步函数、多线程,或者使用std::chrono计算函数的执行时间,然后从1000ms参数中减去它以进入睡眠状态。其中一些对于我的简单案例来说太复杂了,如果我不能很好地理解它们,那么使用其他一些似乎是不安全的

有人能告诉我什么是适合我的要求的解决方案吗?
提前感谢。

您可以避免使用chrono来替代这个更简单的选项。然而,如果您想要μs-ns精度,我强烈建议使用chrono

#include <ctime>

while(//some condition) {

     std::clock_t start = std::clock();
     update();
     std::clock_t end   = std::clock();
     Sleep(1000 - (end - start)/CLOCKS_PER_SEC * 1000);
}
#包括
while(//某些条件){
std::clock_t start=std::clock();
更新();
std::clock_t end=std::clock();
睡眠(1000-(结束-开始)/每秒钟时钟*1000);
}

你需要一直睡到某个时间点,而不是睡一段时间。例如,如果您的第一次更新正好在2:00:00.000,则您未来的更新应尽可能接近2:00:01.000、2:00:02.000等

要实现这一点,您可以指定一个线程进行更新,更新后,进入睡眠状态,直到下次执行计划的更新
chrono::system\u clock::time\u point
此线程::sleep\u until
是执行此操作的工具

例如:

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>

class UpdateManager
{
public:
    explicit UpdateManager() = default;

private:
    static std::atomic<int> now_;
    static std::atomic<bool> stop_;

    struct update_thread
        : private std::thread
    {
        ~update_thread();
        update_thread(update_thread&&) = default;

        using std::thread::thread;
    };

public:
    static update_thread start();
};

void update();

// source

std::atomic<int>  UpdateManager::now_{0};
std::atomic<bool> UpdateManager::stop_{false};

UpdateManager::update_thread::~update_thread()
{
    if (joinable())
    {
        stop_ = true;
        join();
    }
}

UpdateManager::update_thread
UpdateManager::start()
{
    return update_thread{[]
                         {
                             using namespace std;
                             using namespace std::chrono;
                             auto next = system_clock::now() + 1s;
                             while (!stop_)
                             {
                                 update();
                                 this_thread::sleep_until(next);
                                 next += 1s;
                             }
                         }};
}

#include "date/date.h"

void
update()
{
    using namespace date;
    using namespace std;
    using namespace std::chrono;
    cerr << system_clock::now() << '\n';
}

// demo

int
main()
{
    auto t = UpdateManager::start();
    using namespace std;
    this_thread::sleep_for(10s);
}

请参阅此伪代码。如果每个进程(可能需要1秒以上)都是在不同的线程中异步完成的,那么您可以在下一个循环之前完全休眠1秒

void MainGameLoop(bool& running)
{
    while (running)
    {
        AnimateSpritesAsync();
        AnimateBulletsAsync();
        CheckCollisionAsync();
        CheckWinConditionsAsync();

        WaitPreciselyOneSecond();
    }
}
例如,
update
函数如下所示:

while(//some condition) {
     update();
     Sleep(1000);
}
void update(); //your update 

void UpdateAsync()  // the async update
{
   std::thread([]() { update(); }).detach();
}
现在您可以:

void MainGameLoop(bool& running)
    {
        while (running)
        {
            UpdateAsync();    
            Sleep(1000); // i won't recommend Sleep tho
        }
    }

确保在正确的时间发生某些事情的最佳方法是在while循环中使用
this\u thread::sleep\u until()
,这是其他一些人建议的

我喜欢确保我的循环从秒的底部开始,这样就可以使用chrono
time\u-since\u-epoch计算出
next\u full\u second
时间点

interval
变量可以设置为秒或毫秒。用于打印出漂亮的时间值

#include <chrono>
#include <iostream>
#include <thread>

#include "date/date.h"

using namespace date;
using namespace std;
using namespace std::chrono;

int main()
{

    system_clock::time_point now = system_clock::now();
    auto s = duration_cast<seconds>(now.time_since_epoch());
    system_clock::time_point next_full_second = system_clock::time_point(++s);

    auto interval = seconds(1); // or milliseconds(500) or whatever
    auto wait_until = next_full_second;

    while (1)
    {
        this_thread::sleep_until(wait_until);
        cout << system_clock::now() << endl;

        // do something

        wait_until += interval;
    }

    return 0;
}
#包括
#包括
#包括
#包括“日期/日期.h”
使用名称空间日期;
使用名称空间std;
使用名称空间std::chrono;
int main()
{
系统时钟::时间点现在=系统时钟::现在();
自动s=持续时间(现在。时间(从新纪元开始)();
系统时钟::时间点下一个完整秒=系统时钟::时间点(++s);
自动间隔=秒(1);//或毫秒(500)或其他
自动等待\u直到=下一个\u满\u秒;
而(1)
{
此线程::sleep_until(wait_until);

cout“使用std::chrono计算函数执行时间并从1000ms参数中减去它以使其休眠”我建议这是最简单的方法之一。“使用std::chrono计算函数执行时间并从1000ms参数中减去它”:听起来你已经有答案了,你到底想从我们这里得到什么?编辑哦,来吧!我用硬件定时器中断做过一次。硬件将在1000毫秒(加或减大约1个时钟周期)时分支到代码地址,执行代码(这应该很短,所需时间远小于1000毫秒,然后返回。硬件中断取决于硬件(否,duh),所以我不知道它是否适用于您的特定场景。这只是一种很好且准确的实现方法。您有一些吗?您在游戏中使用了哪些图形库?或者什么?@the_Storytler我知道您在说什么,但我在嵌入式系统中也做过类似的工作,不确定如何在桌面应用程序中做到这一点.
Sleep
是WinAPI特有的。在POSIX上,它可能是其他的东西,或者可能是@basileStrynkevich,我从他的例子中使用了它。我假设Sleep是他定制的函数。非常感谢!但这种回答就是我所说的对于我的简单场景来说太复杂的意思。只需
Sleep\u直到
而不是
Sleep_谢谢,我会看的up@Yosry相关部分是:使用名称空间std;使用名称空间std::chrono;auto next=system_clock::now()+1s;while(!stop_){update();this_thread::sleep_until(next);next+=1s;}关键是通过“now”获取起始时间点,通过递增1和“等待”下一个时间点来设置每个下一个时间点。我不知道如何异步调用函数。