如何在不停止应用程序的情况下延迟功能

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。对于您的实际用例,线程可能(或可能不会)过大。 “延迟功能”是什么意思?您想要并发,即在应用程序停止时执行sendCommands,还是只想推迟 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 的东西,不使用 printfCLOCK_PER_SECchar*clock 等。即使使用这个简单的示例,当您开始使用字符串而不是“Command1”文字。 std::string 将在这里为您提供帮助。

【讨论】:

当我尝试这段代码时出现错误,表明 async 不是 std 的成员 @sumitkang 我已经添加了缺少的标题 @sumitkang C++ 中的标准头文件格式为&lt;future&gt;,不带后缀。对于 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数据库

PostgreSQL:如何在不延迟插入响应的情况下执行插入触发器?

如何在不使用睡眠的情况下在 C# 中执行短暂的延迟?

如何在不停止相机馈送的情况下使用闪光灯?