如何在不停止应用程序的情况下延迟功能
Posted
技术标签:
【中文标题】如何在不停止应用程序的情况下延迟功能【英文标题】:How to delay a function without stopping the application 【发布时间】:2015-09-18 03:34:20 【问题描述】:void sendCommand(float t,char* cmd)
std::clock_t endwait;
double endwait = clock () + t * CLOCKS_PER_SEC ;
while (clock() < endwait)
if( clock() < endwait)
printf("\nThe waited command is =%s",cmd);
void Main()
sendCommand(3.0,"Command1");
sendCommand(2.0,"Command2");
printf("\nThe first value")
return 0;
我想延迟一个功能,但我的应用程序应该继续运行。
在上面的代码中,我希望首先打印第一个值。 比我希望打印 Command2 并且 Command1 应该是最后一个打印。
【问题讨论】:
你需要使用线程。 看看boost::asio
,它非常灵活,不仅适用于IO。对于您的实际用例,线程可能(或可能不会)过大。
“延迟功能”是什么意思?您想要并发,即在应用程序停止时执行sendCommand
s,还是只想推迟 printf 后面的函数调用?
@sumitkang 命令的处理顺序重要吗?如果是这样,您需要一个队列来序列化工作。
命令可以按任何顺序处理,但时间延迟应与函数中指定的一致。
【参考方案1】:
我更喜欢std::async
。
#include <chrono>
#include <thread>
#include <future>
#include <iostream>
void sendCommand(std::chrono::seconds delay, std::string cmd)
std::this_thread::sleep_for( delay );
std::cout << "\nThe waited command is =" << cmd;
int main()
auto s1 = std::async(std::launch::async, sendCommand, std::chrono::seconds(3),"Command1");
auto s2 = std::async(std::launch::async, sendCommand, std::chrono::seconds(2),"Command2");
std::cout << "\nThe first value" << std::flush;
s1.wait();
s2.wait();
return 0;
但是,对于实际设计,我会创建一个调度器(或者最好使用现有的调度器)来管理按延迟时间排序的优先级队列。为每个命令生成一个新线程将很快成为一个问题。由于您已将问题标记为 MS VIsual C++,请查看 the PPL which implements task-based parallelism。
由于这是一个 C++ 问题,我会远离 C 的东西,不使用 printf
、CLOCK_PER_SEC
、char*
、clock
等。即使使用这个简单的示例,当您开始使用字符串而不是“Command1”文字。 std::string
将在这里为您提供帮助。
【讨论】:
当我尝试这段代码时出现错误,表明 async 不是 std 的成员 @sumitkang 我已经添加了缺少的标题 @sumitkang C++ 中的标准头文件格式为<future>
,不带后缀。对于 C 功能,标题看起来像 cstdio
。
错误 2 错误 C2664: 'void (std::chrono::milliseconds,char *)' : 无法将参数 1 从 'const char *' 转换为 'std::chrono::milliseconds' c :\program 文件 (x86)\microsoft visual studio 11.0\vc\include\functional 1152 1 ConsoleApplication1
@sumitkang 我已将代码更改为使用std::string
。这也解决了字符串参数的生命周期问题,因为它复制了字符串。【参考方案2】:
我认为你需要线程。你可以这样做:
#include <thread>
#include <chrono>
#include <iostream>
void sendCommand(float t, char const* cmd)
std::this_thread::sleep_for(std::chrono::milliseconds(int(t * 1000)));
std::cout << "\nThe waited command is = " << cmd << '\n';
int main()
// each function call on a new thread
std::thread t1(sendCommand, 3.0, "Command1");
std::thread t2(sendCommand, 2.0, "Command2");
// join the threads so we don't exit before they finish.
t1.join();
t2.join();
【讨论】:
我尝试使用线程作为我的头文件,但编译器无法打开该文件。 我使用的是visual studio 2012 express版。 为什么不使用 std::chrono::seconds? @sumitkang 我对VS2012不熟悉,是否支持C++11
?它需要支持这个答案才能工作,还需要打开它(不确定你是如何在 VS 中做到这一点的)。
@Jens 调用者传入 float 秒数。如果我使用std::chrono::seconds
,那么小数部分会丢失。【参考方案3】:
你可以根据你的实际逻辑以多种方式做到这一点。 示例;:
1.你可以设置一个全局标志变量并检查它的状态,当第三次打印完成时你可以将标志设置为1,这样下一个调用就会执行。
2.您可以使用 STACK .push 堆栈中的所有函数指针。然后弹出并执行。
3.多线程。您可以通过适当的同步方式使用它,但它会很复杂。这取决于您的要求。
谢谢!!!
【讨论】:
我不能使用全局变量,因为我可以有多个发送命令函数。 在这种情况下使用堆栈。【参考方案4】:boost::asio
很好,因为它不需要多线程的开销。
#include <iostream>
#include <boost/asio.hpp>
using namespace std;
int main()
boost::asio::io_service svc;
boost::asio::deadline_timer t0svc;
boost::asio::deadline_timer t1svc;
boost::asio::deadline_timer t2svc;
t0.expires_from_now(boost::posix_time::seconds1);
t1.expires_from_now(boost::posix_time::seconds2);
t2.expires_from_now(boost::posix_time::seconds3);
t2.async_wait([] (const boost::system::error_code& ec) if(!ec) std::cout << "Greetings from t2!\n";);
t1.async_wait([] (const boost::system::error_code& ec) if(!ec) std::cout << "Greetings from t1!\n";);
t0.async_wait([] (const boost::system::error_code& ec) if(!ec) std::cout << "Greetings from t0!\n";);
svc.post([] () std::cout << "I'm number one!\n";);
svc.run();
return 0;
给出输出:
I'm number one!
Greetings from t0!
Greetings from t1!
Greetings from t2!
【讨论】:
以上是关于如何在不停止应用程序的情况下延迟功能的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 sleep() 的情况下使用 ontimer 函数延迟进程?
如何在 pthread 中创建准确的纳秒延迟以及如何在不中断的情况下运行程序的 pthread 部分?
如何在不停止Mysql服务的情况下,定时备份mysql数据库