如何在不使用睡眠/暂停代码的情况下延迟功能?
How could one delay a function without the use of sleep / suspending the code?
我需要将某个函数延迟 x 时间。问题是我不能使用睡眠,也不能使用任何暂停该功能的功能(那是因为该功能是一个包含更多功能的循环,睡眠/暂停一个将睡眠/暂停所有)
有什么办法可以做到吗?
如果你想在某个时间间隔执行一些特定的代码并且不想使用线程(能够暂停),那么你必须跟踪时间并在延迟时执行特定的代码超时了。
示例(伪):
timestamp = getTime();
while (true) {
if (getTime() - timestamp > delay) {
//main functionality
//reset timer
timestamp = getTime();
}
//the other functionality you mentioned
}
使用这种方法,您可以在 delay
指定的每个时间间隔调用一个特定的函数。其他函数将在循环的每次迭代中调用。
换句话说,延迟一个函数或在特定时间间隔执行它都没有区别。
假设您需要 运行 在具有自定义延迟的循环中使用自己的参数运行函数,并在每次迭代之前等待它们完成:
#include <cstdio>
void func_to_be_delayed(const int &idx = -1, const unsigned &ms = 0)
{
printf("Delayed response[%d] by %d ms!\n", idx, ms);
}
#include <chrono>
#include <future>
template<typename T, typename ... Ta>
void delay(const unsigned &ms_delay, T &func, Ta ... args)
{
std::chrono::time_point<std::chrono::high_resolution_clock> start = std::chrono::high_resolution_clock::now();
double elapsed;
do {
std::chrono::time_point<std::chrono::high_resolution_clock> end = std::chrono::high_resolution_clock::now();
elapsed = std::chrono::duration<double, std::milli>(end - start).count();
} while(elapsed <= ms_delay);
func(args...);
}
int main()
{
func_to_be_delayed();
const short iterations = 5;
for (int i = iterations; i >= 0; --i)
{
auto i0 = std::async(std::launch::async, [i]{ delay((i+1)*1000, func_to_be_delayed, i, (i+1)*1000); } );
// Will arrive with difference from previous
auto i1 = std::async(std::launch::async, [i]{ delay(i*1000, func_to_be_delayed, i, i*1000); } );
func_to_be_delayed();
// Loop will wait for all calls
}
}
注意:此方法可能会在每次调用 std::launch::async
类型的策略时产生额外的线程。
标准解决方案是实现事件循环。
如果你使用一些库、框架、系统API,那么很可能有类似的东西可以解决这类问题。
例如Qt有QApplication
提供这个循环,还有QTimer
。
boost::asio
有 io_context
它提供了定时器可以是 运行 boost::asio::deadline_timer
.
的偶数循环
您也可以尝试自己实现这样的事件循环。
提升示例:
#include <boost/asio.hpp>
#include <boost/date_time.hpp>
#include <exception>
#include <iostream>
void printTime(const std::string& label)
{
auto timeLocal = boost::posix_time::second_clock::local_time();
boost::posix_time::time_duration durObj = timeLocal.time_of_day();
std::cout << label << " time = " << durObj << '\n';
}
int main() {
boost::asio::io_context io_context;
try {
boost::asio::deadline_timer timer{io_context};
timer.expires_from_now(boost::posix_time::seconds(5));
timer.async_wait([](const boost::system::error_code& error){
if (!error) {
printTime("boom");
} else {
std::cerr << "Error: " << error << '\n';
}
});
printTime("start");
io_context.run();
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
}
return 0;
}
https://godbolt.org/z/nEbTvMhca
C++20 引入了 coroutines,这也是一个很好的解决方案。
我需要将某个函数延迟 x 时间。问题是我不能使用睡眠,也不能使用任何暂停该功能的功能(那是因为该功能是一个包含更多功能的循环,睡眠/暂停一个将睡眠/暂停所有)
有什么办法可以做到吗?
如果你想在某个时间间隔执行一些特定的代码并且不想使用线程(能够暂停),那么你必须跟踪时间并在延迟时执行特定的代码超时了。
示例(伪):
timestamp = getTime();
while (true) {
if (getTime() - timestamp > delay) {
//main functionality
//reset timer
timestamp = getTime();
}
//the other functionality you mentioned
}
使用这种方法,您可以在 delay
指定的每个时间间隔调用一个特定的函数。其他函数将在循环的每次迭代中调用。
换句话说,延迟一个函数或在特定时间间隔执行它都没有区别。
假设您需要 运行 在具有自定义延迟的循环中使用自己的参数运行函数,并在每次迭代之前等待它们完成:
#include <cstdio>
void func_to_be_delayed(const int &idx = -1, const unsigned &ms = 0)
{
printf("Delayed response[%d] by %d ms!\n", idx, ms);
}
#include <chrono>
#include <future>
template<typename T, typename ... Ta>
void delay(const unsigned &ms_delay, T &func, Ta ... args)
{
std::chrono::time_point<std::chrono::high_resolution_clock> start = std::chrono::high_resolution_clock::now();
double elapsed;
do {
std::chrono::time_point<std::chrono::high_resolution_clock> end = std::chrono::high_resolution_clock::now();
elapsed = std::chrono::duration<double, std::milli>(end - start).count();
} while(elapsed <= ms_delay);
func(args...);
}
int main()
{
func_to_be_delayed();
const short iterations = 5;
for (int i = iterations; i >= 0; --i)
{
auto i0 = std::async(std::launch::async, [i]{ delay((i+1)*1000, func_to_be_delayed, i, (i+1)*1000); } );
// Will arrive with difference from previous
auto i1 = std::async(std::launch::async, [i]{ delay(i*1000, func_to_be_delayed, i, i*1000); } );
func_to_be_delayed();
// Loop will wait for all calls
}
}
注意:此方法可能会在每次调用 std::launch::async
类型的策略时产生额外的线程。
标准解决方案是实现事件循环。 如果你使用一些库、框架、系统API,那么很可能有类似的东西可以解决这类问题。
例如Qt有QApplication
提供这个循环,还有QTimer
。
boost::asio
有 io_context
它提供了定时器可以是 运行 boost::asio::deadline_timer
.
您也可以尝试自己实现这样的事件循环。
提升示例:
#include <boost/asio.hpp>
#include <boost/date_time.hpp>
#include <exception>
#include <iostream>
void printTime(const std::string& label)
{
auto timeLocal = boost::posix_time::second_clock::local_time();
boost::posix_time::time_duration durObj = timeLocal.time_of_day();
std::cout << label << " time = " << durObj << '\n';
}
int main() {
boost::asio::io_context io_context;
try {
boost::asio::deadline_timer timer{io_context};
timer.expires_from_now(boost::posix_time::seconds(5));
timer.async_wait([](const boost::system::error_code& error){
if (!error) {
printTime("boom");
} else {
std::cerr << "Error: " << error << '\n';
}
});
printTime("start");
io_context.run();
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
}
return 0;
}
https://godbolt.org/z/nEbTvMhca
C++20 引入了 coroutines,这也是一个很好的解决方案。