3

スレッドが参加していない場合にスレッドを中断する方法 (できればブースト スレッドを使用) を探しています。複数のスレッドを開始し、200 ミリ秒までに終了していないスレッドを終了したいと考えています。私はこのようなことを試しました

boost::thread_group tgroup;
tgroup.create_thread(boost::bind(&print_f));
tgroup.create_thread(boost::bind(&print_g));
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
tgroup.interrupt_all();

これで動作し、200 ミリ秒後にすべてのスレッドが終了します。ただし、これらのスレッドが 200 ミリ秒前に終了する場合は、これらのスレッドに参加したいと思います。一定時間内に終了しない場合に参加して中断する方法はありますか?

編集:タイムアウト前に参加する必要がある理由:

速度が非常に重要なサーバーを作成しています。残念ながら、他のサーバーにいくつかの情報を要求する必要があります。したがって、これらの呼び出しを並行して行い、できるだけ早く終了したいと考えています。サーバーの処理に時間がかかりすぎる場合は、そのサーバーからの情報を無視して、情報なしで続行する必要があります。したがって、タイムアウト時間は、待機できる最大時間です。タイム タイムアウト タイマーを待つ代わりに、すべての応答が受信されたときに熟考を続けることができることは、私にとって非常に有益です。それで、私のプログラムは次のようになります:

・お客様からのご依頼を承ります。

-情報を解析します。

スレッドを作成する

-複数の他のサーバーに情報を送信します。

-サーバーから情報を取得します。

-サーバーからの情報を共有キューに入れます。

エンドスレッド

-共有キューからの情報を解析します。

・お客様に情報を返す

4

2 に答える 2

3

最新の Boost と C++11 を使用している場合は、try_join_for()( http://www.boost.org/doc/libs/1_53_0/doc/html/thread/thread_management.html#thread.thread_management.thread.try_join_forを使用します) )。それ以外の場合は、timed_join()( http://www.boost.org/doc/libs/1_53_0/doc/html/thread/thread_management.html#thread.thread_management.thread.timed_join ) を使用します。

于 2013-04-10T14:56:42.623 に答える
3

使用したいのは、おそらくスコープ付きスレッドのセットであり、タイムアウト後に残りのすべてのスレッドで終了を呼び出します。残念ながら、スレッド グループとスコープ スレッドを一緒に使用することはできません。

スレッド グループ クラスは、実際には非常に単純なコンテナーです。そのスレッドへのポインターがまだない場合、そのスレッドを削除することはできません。また、グループによって作成されたスレッドへのポインターを取得することもできません。クラス API もあまり提供しません。これは、あなたの状況での管理を少し妨げています。

残りのソリューションは、グループ外でスレッドを作成することに依存しており、終了直前にそれぞれのスレッドに特定のタスクを実行させます。出来た:

  • グループから自分自身を削除し、
  • 次に、自分自身を別のグループに追加します

管理スレッドはjoin_all、後者のグループを呼び出し、前者と同じように動作する必要があります。

using namespace boost;
void thread_end(auto &thmap, thread_group& t1, thread_group& t2, auto &task){
    task();
    thread *self = thmap[this_thread::get_id()];
    t1.remove_thread(&self);
    t2.add_thread(&self);
}

 std::map<thread::id, thread *> thmap;
thread_group trunninggroup;
thread_group tfinishedgroup;
thread *th;
th = new thread(
    bind(&thread_end, thmap, trunninggroup, tfinishedgroup, bind(&print_f)));
thmap[th->get_id()] = th;
trunninggroup.add_thread(th);
th = new thread(
    bind(&thread_end, thmap, trunning_group, tfinishedgroup, bind(&print_g)));
thmap[th->get_id()] = th;
trunninggroup.add_thread(th);
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
tfinishedgroup.join_all();
trunninggroup.interrupt_all();

しかし、これは、管理スレッドが実際に発生したときにスレッドの終了を実際に通知したい場合には理想的ではありません (とにかく、それが何か役に立つかどうかはわかりません)。通知を受けるための解決策は、おそらく次のとおりです。

  • 上記のようにグループの移行を行います
  • 次に、管理スレッドが実行している条件変数をトリガーしますtimed_wait

ただし、通知された後の残り時間を追跡するために時間計算を行い、その残り時間でスリープを再開する必要があります。それは、そのタスクに使用される Duration クラスに完全に依存します。

アップデート

全体像を見て、私はまったく別のアプローチを試みます: すでに終了しているスレッドを終了することは問題ではないと思うので、それらをすべてグループに残し、グループを使用してそれらを作成します。コードはそれを示しています。

ただし、すべてのスレッドが完了するとすぐに、またはタイムアウト後に管理スレッドを起動しようとします。これは、thread_groupクラスが単独で提供するものでは実行できませんが、カスタムメイドのセマフォ、または のパッチを適用したバージョンboost::barrierを使用して、時間指定待機を許可することで実行できます。

基本的には、グループ内のスレッドの数に 1 を加えた数 (メイン スレッド) にバリアを設定し、メイン スレッドの時間を待機させます。各ワーカー スレッドはその作業を行い、終了すると、その結果をキューとwaitバリアに投稿します。すべてのワーカー スレッドがタスクを完了すると、全員が待機し、バリアがトリガーされます。

次に、メイン スレッド (他のすべてのスレッドと同様ですが、問題ではありません) が起動し、グループを終了して処理を続行し、結果を処理できます。それ以外の場合は、タイムアウト時に起動され、とにかく同じことを行います。

のパッチ適用はboost::barrierそれほど難しくないはずです。メソッドを複製し、内部waitの条件変数を a に置き換えるだけで済みます(コードは見ていませんが、この仮定は完全に的を射ているかもしれません)。それ以外の場合は、この質問に対してサンプルのセマフォ実装を提供しましたが、パッチも難しくありません。waittimed_wait

最後の考慮事項: 通常、スレッドを終了することは最善の方法ではありません。代わりに、中断する必要があるスレッドにシグナルを送って待機するか、何らかの方法で、未完了のタスクを補助スレッドに渡して、順次クリーンアップする必要があります。その後、スレッド グループは次のタスクに取り組む準備が整い、スレッドを常に破棄して作成する必要がなくなります。これは、多少コストのかかる操作です。アプリケーションのコンテキストでタスクの概念を形式化し、新しいタスクを取得して処理するためにスレッドをループで実行する必要があります。

于 2013-04-10T15:25:58.020 に答える