2014-01-11 66 views
8

我正在寫一個程序在C++中,我需要定期調用一個函數,每隔10ms左右調用一個函數。我從來沒有做過任何與C++中的時間或時鐘相關的任何事情,這是一個快速簡單的問題還是其中沒有完整解決方案的問題?需要定期調用一個函數在c + +中

謝謝!

+0

''有這種支持。 – chris

回答

13

一個簡單的定時器可以實現如下,

#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); 
} 

這種簡單的解決方案並沒有提供一種方法來停止計時器。計時器將繼續運行,直到程序退出。

+0

很酷,我也學習如何通過這個例子創建一個新的線程。 – 123iamking

+5

@ user534498不幸的是,你的解決方案不會做他所問的。它會在兩次調用之間用'interval'延遲執行'func'。它不會每'間隔'執行'func'。如果'func'可能需要一段時間才能運行,則啓動時間也會有所不同。 – ilya1725

0

這取決於你將在每個區間做什麼 - 在屏幕/窗體的特定位置顯示時間/代碼或其他內容。或者您可能需要將常規數據發送到某個連接的機器(通過套接字或管道)。你真的需要10毫秒的精度嗎?

根據要求,特別是精度要求,你可能有專門的線程做'東西',然後等待,再做同樣的事情。或者,在Windows上,您可以使用SetTimer在每個時間間隔觸發WM_TIMER事件(它不需要線程)。你也可以使用等待定時器,多媒體定時器等。

最後,但相當重要 - 你需要平臺和編譯器的兼容性嗎?意思是說,你將使用哪種操作系統,還是你需要平臺獨立?您正在尋找哪些編譯器功能(C++ 11,C++ 14或pre C++ 11)。

0

如果你使用Visual C++編碼,你可以添加一個計時器元素到你想要調用周期函數的表單中(這裏叫做我的表單是MainForm,我的計時器是MainTimer)。在「事件」中添加對tick事件的調用。設計師將在您的.h文件中添加這樣一行:

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

然後,在每個時間間隔(以毫秒爲單位指定),應用程序將調用這個函數

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

注意:這是C++/CLI代碼而不是標準C++。 – crashmstr

7

要完成的問題,代碼從@ user534498可以很容易地適應有周期性的時間間隔。 只需確定計時器線程循環開始時的下一個開始時間點,並在執行該函數後確定該時間點。

#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) 
    ; 
} 
+0

這是正確的方法,只要注意'func()'必須在'sleep_until'結束之前完成! –

0

對不起,但我沒有找到比這更簡單的設計。

你可以,讓擁有兩個線程類,以及weak_ptr本身, 是一個「支架」的可調用可以放心地看到它,因爲即使該對象被破壞的可調用 將依然存在。你不想要一個懸掛指針。

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; 
} 
相關問題