2012-03-30 13 views
18

std::thread::join()へのコールにタイムアウトを設定することはできますか?私は、スレッドが実行に時間がかかりすぎる場合や、スレッドを終了する場合を処理したい。私はこれを複数のスレッド(たとえば、最大30)に対して実行している可能性があります。thread.join()のタイムアウト

ブーストなしで行うことをお勧めしますが、これが最善の方法であれば、私はブーストソリューションに興味があります。

+0

時間がなくなったらどうしますか?スレッドは終了しますか? –

+4

これは、 'std :: thread :: native_handle'が使用するものです.OSの機能を使って、タイムド・ジョインを行います。 – ildjarn

答えて

13

std::thread::join()のタイムアウトはありません。しかし、std::thread::join()は単に便利な機能として見ることができます。 condition_variableを使用すると、スレッド間の非常に豊富なコミュニケーションと協力関係を作成できます。例:この例では

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

int thread_count = 0; 
bool time_to_quit = false; 
std::mutex m; 
std::condition_variable cv; 

void f(int id) 
{ 
    { 
    std::lock_guard<std::mutex> _(m); 
    ++thread_count; 
    } 
    while (true) 
    { 
     { 
     std::lock_guard<std::mutex> _(m); 
     std::cout << "thread " << id << " working\n"; 
     } 
     std::this_thread::sleep_for(std::chrono::milliseconds(250)); 
     std::lock_guard<std::mutex> _(m); 
     if (time_to_quit) 
      break; 
    } 
    std::lock_guard<std::mutex> _(m); 
    std::cout << "thread ended\n"; 
    --thread_count; 
    cv.notify_all(); 
} 

int main() 
{ 
    typedef std::chrono::steady_clock Clock; 
    std::thread(f, 1).detach(); 
    std::thread(f, 2).detach(); 
    std::thread(f, 3).detach(); 
    std::thread(f, 4).detach(); 
    std::thread(f, 5).detach(); 
    auto t0 = Clock::now(); 
    auto t1 = t0 + std::chrono::seconds(5); 
    std::unique_lock<std::mutex> lk(m); 
    while (!time_to_quit && Clock::now() < t1) 
     cv.wait_until(lk, t1); 
    time_to_quit = true; 
    std::cout << "main ending\n"; 
    while (thread_count > 0) 
     cv.wait(lk); 
    std::cout << "main ended\n"; 
} 

mainは、ミューテックス(これはまた、原子することができる)の下で終了する時間であれば、時折チェックすべてが、仕事をするために複数のスレッドを起動します。また、メインスレッドは終了するかどうかを監視します(スレッドがすべての作業を完了した場合)。メインが忍耐を使い果たすと、彼は終了すると宣言し、終了する前にすべてのスレッドが必要なクリーンアップを実行するのを待ちます。

+1

'thread_count'はアトミックでなければならないので、これは正しくありませんか? –

+1

@MooingDuck:この場合、 'thread_count'が読み書きされる場所はすべて、' m'のロック状態になっているからです。 'thread_count'をアトミックにすることは正しいでしょうが、冗長で不必要に高価になります。 –

+0

実際、私の注意を引いたのは 'while(thread_count> 0)cv.wait(lk);'でした。そのスレッドのうちのどれかが 'thread_count'をキャッシュして「期待通りに」動作できないのでしょうか? –

3

ブーストの場合、join()のタイムアウトのバージョンはtimed_join()を参照してください。

3

timed_join()は廃止予定です。代わりに)(try_join_forを使用します。

myThread.try_join_for(boost::chrono::milliseconds(8000)) 
4

はい、それは可能だ。 Galikによって提案されたソリューションは、次のようになります。

#include <thread> 
#include <future> 
... 
// Launch the thread. 
std::thread thread(ThreadFnc, ...); 
... 
// Terminate the thread. 
auto future = std::async(std::launch::async, &std::thread::join, &thread); 
if (future.wait_for(std::chrono::seconds(5)) 
    == std::future_status::timeout) { 

    /* --- Do something, if thread has not terminated within 5 s. --- */ 

} 

しかし、これは本質的thread.join()を行い、第三のスレッドを起動します。

(注:threadが参加していると、補助スレッドが終了するまでfutureのデストラクタがブロックされます)


は多分ちょうど別のスレッドをダウンさせるためにスレッドを起動するには、あなたが望むものではありません。 T_returnあなたのスレッド手続きの戻り値の型である

#include <thread> 
#include <future> 
... 
// Launch the thread. 
std::future<T_return>* hThread 
    = new std::future<T_return>(std::async(std::launch::async, ThreadFnc, ...)); 
... 
// Terminate the thread. 
if (hThread->wait_for(std::chrono::seconds(5)) 
    == std::future_status::timeout) { 

    /* --- Do something, if thread has not terminated within 5 s. --- */ 

} else 
    delete hThread; 

:補助スレッドのない別の、ポータブルソリューションがあります。このシナリオでは、std::threadの代わりにstd::future/std::asyncの組み合わせが使用されます。

hThreadはポインタです。 delete演算子を呼び出すと、デストラクタが*hThreadとなり、スレッドが終了するまでブロックされます。

私は両方のバージョンをgg 4.9.3でCygwinでテストしました。

+1

良いアプローチですが、私はいくつかのスレッドを待たなければなりません。 (私はstd :: threadスレッド[nrOfThreads]を使用します)最初の解決策はforループのスレッドに適用されますか?タイムアウトが超過すれば、どうすればいいですか? Thx – leon22

+0

前半はすばらしい回避策ですが、後半には意味がありませんが、それは悪いスタイルです:スレッド機能を将来のセマンティクスを持つスレッド機能にすることができるのであれば?なぜ新しいと削除とプレーンポインター?明らかに> = C++ 11について話していたので、この漏洩アプローチは良くありません。そして、ポインタはまったく必要ありません。 – Superlokkus

+0

@ leon22:タイムアウトの処理は、アプリケーションのコンテキストによって異なります。プロセスが終了しようとしている場合、私はログファイルに警告を書き、スレッドを忘却に解放します。他の場合、私はスレッドを殺すかもしれません。プロセスのメインスレッドが終了すると、ほとんどのオペレーティングシステムはプロセス内の他のすべてのスレッドを自動的に終了させます。 – ManuelAtWork

関連する問題