需要在c ++中以周期性的时间间隔调用函数

时间:2014-01-11 02:02:14

标签: c++ visual-c++ timer

我正在用c ++编写一个程序,我需要以周期性的时间间隔调用一个函数,比如每10ms左右。我从来没有做过与c ++中的时间或时钟相关的任何事情,这是一个快速简单的问题还是那些没有简洁解决方案的问题?

谢谢!

8 个答案:

答案 0 :(得分:15)

可以按如下方式实现简单的计时器,

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

void timer_start(std::function<void(void)> func, unsigned int interval)
{
    std::thread([func, interval]() {
        while (true)
        {
            func();
            std::this_thread::sleep_for(std::chrono::milliseconds(interval));
        }
    }).detach();
}


void do_something()
{
    std::cout << "I am doing something" << std::endl;
}

int main() {
    timer_start(do_something, 1000);

    while(true);
}

这个简单的解决方案不提供停止计时器的方法。计时器将继续运行,直到程序退出。

答案 1 :(得分:9)

要完成此问题,可以轻松调整@ user534498中的代码,使其具有周期性的滴答间隔。 只需要确定定时器线程循环的开始时的下一个开始时间点和执行该函数后该时间点的sleep_until

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

void timer_start(std::function<void(void)> func, unsigned int interval)
{
  std::thread([func, interval]()
  { 
    while (true)
    { 
      auto x = std::chrono::steady_clock::now() + std::chrono::milliseconds(interval);
      func();
      std::this_thread::sleep_until(x);
    }
  }).detach();
}

void do_something()
{
  std::cout << "I am doing something" << std::endl;
}

int main()
{
  timer_start(do_something, 1000);
  while (true)
    ;
}

答案 2 :(得分:0)

您可以查看线程:

这是一个用C实现的时间间隔控制函数,使用pthread.h,它应该是一个简单的C ++端口。 Executing a function at specific intervals

答案 3 :(得分:0)

这取决于您每个时间间隔的操作 - 在屏幕/表单的特定位置显示时间/自动收报机或其他内容。或者您可能需要将常规数据发送到某个连接的计算机(通过套接字或管道)。你真的需要10毫秒的精度吗?

根据要求,尤其是精度要求,您可能有专门的线程来执行'某事',然后等待再做同样的事情。或者,在Windows上,您可以使用SetTimer在每个时间间隔触发WM_TIMER事件(它不需要线程)。您也可以使用等待计时器,多媒体计时器等。

最后,但非常重要 - 您是否需要平台和编译器兼容性?这意味着,您将使用哪种操作系统,或者您需要独立于平台?您正在寻找什么编译器功能(C ++ 11,C ++ 14或前C ++ 11)。

答案 4 :(得分:0)

如果您使用Visual C ++进行编码,则可以在要调用周期函数的表单中添加一个计时器元素(此处称为my form为MainForm,而我的计时器为MainTimer) 。在“事件”中添加对tick事件的调用。设计人员会在你的.h文件中添加这样的一行:

this->MainTimer->Enabled = true;
this->MainTimer->Interval = 10;
this->MainTimer->Tick += gcnew System::EventHandler(this, &MainForm::MainTimer_Tick);

然后,在每个间隔(以ms为单位指定),应用程序将调用此函数

private: System::Void MainTimer_Tick(System::Object^  sender, System::EventArgs^  e) {
   /// Enter your periodic code there
}

答案 5 :(得分:0)

很抱歉,但我没有找到比这更简单的设计。

你可以,创建一个既拥有一个线程又拥有一个weak_ptr的类, 成为&#34;持有人&#34;可调用者可以安全地看到它,因为可调用 即使对象被破坏,它仍然存在。你不想要一个悬垂的指针。

template<typename T>
struct IntervalRepeater {
    using CallableCopyable = T;
private:
    weak_ptr<IntervalRepeater<CallableCopyable>> holder;
    std::thread theThread;

    IntervalRepeater(unsigned int interval,
            CallableCopyable callable): callable(callable), interval(interval) {}

    void thread() {
        weak_ptr<IntervalRepeater<CallableCopyable>> holder = this->holder;
        theThread = std::thread([holder](){
            // Try to strongify the pointer, to make it survive this loop iteration,
            //    and ensure that this pointer is valid, if not valid, end the loop.
            while (shared_ptr<IntervalRepeater<CallableCopyable>> ptr = holder.lock()) {
                auto x = chrono::steady_clock::now() + chrono::milliseconds(ptr->interval);
                ptr->callable();
                this_thread::sleep_until(x);
            }
        });
    }

public:
    const CallableCopyable callable;
    const unsigned int interval;

    static shared_ptr<IntervalRepeater<T>> createIntervalRepeater(unsigned int interval,
            CallableCopyable callable) {
        std::shared_ptr<IntervalRepeater<CallableCopyable>> ret =
                shared_ptr<IntervalRepeater<CallableCopyable>>(
                        new IntervalRepeater<CallableCopyable>(interval, callable));
        ret->holder = ret;
        ret->thread();

        return ret;
    }

    ~IntervalRepeater() {
        // Detach the thread before it is released.
        theThread.detach();
    }

};

void beginItWaitThenDestruct() {
    auto repeater = IntervalRepeater<function<void()>>::createIntervalRepeater(
            1000, [](){ cout << "A second\n"; });
    std::this_thread::sleep_for(std::chrono::milliseconds(3700));
}

int main() {
    beginItWaitThenDestruct();
    // Wait for another 2.5 seconds, to test whether there is still an effect of the object
    //   or no.
    std::this_thread::sleep_for(std::chrono::milliseconds(2500));
    return 0;
}

答案 6 :(得分:0)

这是一篇很老的文章,但是我找到了一个非常简单的解决方案,我想 分享:

解决方案是

#include "unistd.h"

并使用上述库中包含的功能

usleep(int) 

例如,这将每3000微秒调用一次函数

int main() {

    int sleep_time = 3000;
    while(true) { 

          usleep(sleep_time);

          call function;
    }

    return 0;
}

我也将它用于串行和并行代码,并且在两种情况下都能正常工作!

答案 7 :(得分:0)

我使自己成为一个异步系统。请勿将其与std::async混淆。由于它是定制的,因此我可以完全控制时间线,因此可以添加,编辑,删除,追加等任务。它主要在单线程中运行,并确保上下文切换之间的安全,但也支持多线程同步。尝试建立自己的异步系统,以我的经验,我认为这是值得的