2014-01-11 62 views
8

私はC++でプログラムを作成しています。定期的な時間間隔、たとえば10msごとに関数を呼び出す必要があります。私は時間や時計に関連することをC++でやったことは一度もありませんでしたが、これはすばやく簡単な問題ですか、それともすてきな解決策がないのでしょうか?は、C++で定期的な時間間隔で関数を呼び出す必要があります

ありがとうございます!あなたがスレッドに見ることができ

+0

」にはこのサポートがあります。 – chris

答えて

0

はここでpthread.hのを使用して、C言語で実装された時間間隔制御機能だ、それはC++への単純なポートである必要があります。次のようにシンプルなタイマーを実装することができ Executing a function at specific intervals

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'を実行します。 'interval 'ごとに' func'を実行することはありません。 'func'が何らかの可変時間を取って起動時間を取ることができるならば、開始時間も変化します。 – ilya1725

0

間隔ごとに何をしているかによって、時間/ティッカーなどをスクリーン/フォームの特定の場所に表示するかどうかによって異なります。または、接続された一部のマシン(ソケットまたはパイプを介して)に定期的なデータを送信する必要があるかもしれません。実際に10ミリ秒の精度が必要ですか?

要件に応じて、特に精度の要求に応じて、「何か」を実行する専用のスレッドがあり、その後同じことを再度実行します。または、Windowsでは、SetTimerを使用して、各間隔でWM_TIMERイベントをトリガーします(スレッドを必要としません)。待機可能なタイマー、マルチメディアタイマーなどを使用することもできます。

最後に重要ですが、プラットフォームとコンパイラの互換性が必要ですか?つまり、どのOSを使用するのか、プラットフォームに依存しないのかということですか?探しているコンパイラ機能(C++ 11、C++ 14、またはC++ 11以前)。

0

Visual C++でコーディングする場合は、定期的な関数(ここでは私のフォームはMainFormと呼ばれ、私のタイマーはMainTimerです)と呼ばれるフォームにタイマー要素を追加することができます。 「イベント」のティックイベントへの呼び出しを追加します。デザイナーがあなたの.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から、周期的なティック間隔を持つように容易に適合させることができる。 タイマスレッドループのbeginnigで次の開始時点を決定する必要があり、関数を実行した後にその時点の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) 
    ; 
} 
+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; 
} 
関連する問題