2016-07-01 20 views
-2

2つのタスクを定期的に実行する必要があるプログラムを実行しようとしています。 たとえば、タスク1を10秒ごとに実行し、タスク2を20秒ごとに実行します。複数のスレッドを開始するC++スレッド

私が考えているのは、それぞれがタイマー付きの2つのスレッドを作成することです。スレッド1は、10秒ごとにタスク1の新しいスレッドを起動します。スレッド2は20秒ごとにタスク2の新しいスレッドを起動します。

私の疑問は、以前のタスク1が完了していない場合は、新しいタスク1を起動する方法ですか?

while (true) 
{ 
    thread t1 (task1); 
    this_thread::sleep_for(std::chrono::seconds(10)); 
    t1.join(); 
} 

私はこれを試していましたが、この方法では、前のタスクが完了すると新しいタスク1が開始されます。

編集:

基本的に私はタスクスケジューラを実装したいと思います。 タスク1をX秒ごとに実行します。 タスク2をY秒ごとに実行します。 私はこのような何かに考えていた:

thread t1 (timer1); 
thread t2 (timer2); 


void timer1() 
{ 
    while (true) 
    { 
     thread t (task1); 
     t.detach() 
     sleep(X); 
    } 

} 

同じタイマ2とタスク2

+2

[MCVE]を投稿してください。実際に 'task1'とは何ですか? –

+0

それは重要ですか?私はまだtask1を実装していません。しかし、いくつかの値を計算してデータベースに格納する単純な関数です – jcmpoliveira

+0

2つのtask1を同時に実行する必要がありますか?あなたは1つのtask1スレッドを手放すことができます。ここで、task1が早く終了すると、スレッドは再び実行されるまでスリープします。そうでなければループして再実行しますか? – user4581301

答えて

0

のためにあなたはそれがthread::join()を使用しないようにしたい、定義により、仕上がりにスレッドを待ちます。代わりに、眠る前にthread::detachを使用してください。そのため、待つ必要はありません。

私はおそらく、あなたは一つのタスクごとにt秒をスケジュールする責任があるperiodic_taskハンドラを作成することができ、それにhttp://www.cplusplus.com/reference/thread/thread/detach/

+1

'detach'を使用することを盲目的に推奨しません。すべてが正しく動作することを保証します。 –

+0

これをどうやって実装しますか? – jcmpoliveira

+1

@jcmpoliveira現時点で適切な回答を提供するための詳細は不十分です。 –

1

を読んでお勧めしたいです。そして、プログラム内のどこからでも特定の機能と時間を使ってperiodic_taskを起動することができます。

以下、私は何かをスケッチしました。 1つの有効な選択肢は、スレッドを切り離して永久に実行させることです。もう1つは、親スレッドがキャンセル/結合を許可するキャンセルを含めることです。私は後者を可能にする機能を含んでいます(あなたは引き離しても忘れても構いませんが)。

#include <condition_variable> 
#include <functional> 
#include <iostream> 
#include <mutex> 
#include <thread> 

class periodic_task 
{ 
    std::chrono::seconds d_; 
    std::function<void()> task_; 
    std::mutex mut_; 
    std::condition_variable cv_; 
    bool cancel_{false}; 

public: 
    periodic_task(std::function<void()> task, std::chrono::seconds s) 
     : d_{s} 
     , task_(std::move(task)) 
     {} 

    void 
    operator()() 
    { 
     std::unique_lock<std::mutex> lk{mut_}; 
     auto until = std::chrono::steady_clock::now(); 
     while (true) 
     { 
      while (!cancel_ && std::chrono::steady_clock::now() < until) 
       cv_.wait_until(lk, until); 
      if (cancel_) 
       return; 
      lk.unlock(); 
      task_(); 
      lk.lock(); 
      until += d_; 
     } 
    } 

    void cancel() 
    { 
     std::unique_lock<std::mutex> lk{mut_}; 
     cancel_ = true; 
     cv_.notify_one(); 
    } 
}; 

void 
short_task() 
{ 
    std::cerr << "short\n"; 
} 

void 
long_task(int i, const std::string& message) 
{ 
    std::cerr << "long " << message << ' ' << i << '\n'; 
} 

int 
main() 
{ 
    using namespace std::chrono_literals; 
    periodic_task task_short{short_task, 7s}; 
    periodic_task task_long{[](){long_task(5, "Hi");}, 13s}; 
    std::thread t1{std::ref(task_short)}; 
    std::this_thread::sleep_for(200ms); 
    std::thread t2{std::ref(task_long)}; 
    std::this_thread::sleep_for(1min); 
    task_short.cancel(); 
    task_long.cancel(); 
    t1.join(); 
    t2.join(); 
} 
+0

こんにちは、ありがとう。 しかし、この方法では前のタスクが終了するタスクが1つだけ開始されます。右? – jcmpoliveira

+0

@jcmpoliveira:そうです。それがあなたが望むものでないならば、おそらくあなたはこれをあなたが望むものとまったく同じように修正することができます。この回答は、どのように複雑であっても、mutexesとcondition_variablesを使用してスレッド間であらゆる種類の通信を確立する方法を示しています。 –

+0

しかし、mutexのポイントは何ですか? スレッドt1とt2は、これらのリソースにアクセスするために競合しないためです。右? t1とt2は、periodic_taskクラスの2つの異なるオブジェクトで実行されています。 – jcmpoliveira

関連する問題