每1秒调用一个函数(精确) 我正在研究一个简单的C++游戏模拟程序,有一个UpDeDeO()函数更新游戏的当前状态,它必须精确地每隔1秒调用一次。如果我使用这样的循环: while(//some condition) { update(); Sleep(1000); } void update(); //your update void UpdateAsync() // the async update { std::thread([]() { update(); }).detach(); }
那么函数将不会每隔1秒调用一次,而是每隔(1+update()的执行时间)调用一次。 我读过各种解决方案,比如异步函数、多线程,或者使用std::chrono计算函数的执行时间,然后从1000ms参数中减去它以进入睡眠状态。其中一些对于我的简单案例来说太复杂了,如果我不能很好地理解它们,那么使用其他一些似乎是不安全的 有人能告诉我什么是适合我的要求的解决方案吗?每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
提前感谢。您可以避免使用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()
,这是其他一些人建议的
我喜欢确保我的循环从秒的底部开始,这样就可以使用chronotime\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和“等待”下一个时间点来设置每个下一个时间点。我不知道如何异步调用函数。