2011-09-13 15 views
2

私の問題は本当にシンプルな解決策かもしれませんが、私は本当に私の周りのすべてのブーストに混乱しています。メイン操作をブロック/待機せずに新しいスレッドを開始

はここに私の問題だ:

私はCallbackReceived関数を呼び出すコールバックシステムによって発生したタスク(計算、ファイルシステム操作など)を、開始したいと私はスレッドに、この操作を渡したいです、典型的にはオブジェクトのメンバ関数によって表される。スレッドは終了を保証されていないので、しばらくしてからスレッドをキャンセルする必要があります。以下のような

何か(これは100%正しいかどうかわからない):

// ... 
MyObject object; 
// ... 
void CallbackReceived(int parameter) { 
    boost::thread tThread(&MyObject::calculate, *&object); 

    boost::asio::deadline_timer tDeadlineTimer(_ioService, boost::posix_time::seconds(2)); 
    tDeadlineTimer.async_wait(boost::bind(DeadlineTimeOut, boost::asio::placeholders::error)); 

    tThread.join(); 
} 

基本的には、tThread.joinは() `スレッドの復帰を待ちます。待っている間、私のメインは、ブロックされて眠っているので、入ってくる可能性のあるコールバックを受け取ることができませんでした。

スレッドを実行し、操作を実行中に呼び出し元の初期プログラムをブロックしないようにするには、何ができますか?

+1

... 'join'を呼び出しませんか? ':S' –

+1

tThreadはtThread.join()のように使うポインタではないので、あなたのコードはあなたが実際に行っているものとは異なるもののようです。また、スレッドの終了を待機したくない場合は、joinをコールしないでください。多分未来はあなたのためのより良いツールですか? – PlasmaHH

+0

@PlasmaHHヒントありがとう、私はそれを逃した。 – Benjamin

答えて

2

計算結果はどうしますか?

メインスレッドは.join()でブロックされています。

他のコールバックを処理する場合は、通常の実行フローに戻り、別のコールを待つ必要があります。

次に、終了時に計算した結果をあなた自身に聞かせてください。たぶんスレッドは結果をどこかの共有リソースに入れて正常に終了することができます。

コードの処理(コールバックの処理、スレッドの開始、結果の処理)をすべて整理してから実装することを検討する必要があります。 boostとC++ 11には、あなたに合った約束と未来という新しい構造がありますが、まずあなたが望むものについて考える必要があります。

+0

あなたは正しいです。結果はどこかに保存されますが、この場合は問題になりません。たぶんプリントアウトしているだけかもしれません。しかし、あなたは、スレッドが常に終了するつもりはないことを思い出しました、私は念頭に置いて忘れてしまった。したがって、時間の経過後にキャンセルする必要があります。トピックを少し変更しました。そのご迷惑をおかけして申し訳ありません。 – Benjamin

3

joinは、計算結果が必要なときに呼び出すことができます。 「未来」パターンのようなもの。とにかく、スレッド変数をグローバルなCallBackRecieved関数にグローバルにする必要があります(ラッパーを書くことができます)。 注:スレッドが終了したときにjoinを呼び出すことができます。その作業は何もブロックされません。

0

実際には、メインスレッドがスリープしている間にコールバックを呼び出すことができます。スレッドのコンテキスト(スタック)上で実行されます。

あなたはおそらく、参加している時点では参加を呼びたくないかもしれませんが、後でまたは決して参加しないでください。

例(擬似コード):

class Worker { 

    void doWork(void * mainthread){ 

    Main* main = static_cast<Main*>(mainthread); 

    while(hasWorkTodo){ 
     //work 

     //inform main 
     main->callbackwithinformation(information); 

    } 


} 


class Main{ 

    atomi_int filesfound; 

    void main_part(){ 
    //start worker 
    boost::thread thread(&Worker::doWork, &object, this); 

    while(hasworktodo){ 
     //do work 

     //use filesfound here 
    } 
    //About to finish make sure we join our thread 
    thread.join(); 

    } 

    void callbackwithinformation(int updatedcount){ 
    //here we set a flag or pass some object 
    //probably will need an atomic operation 
    filesfound = updatedcount; 
    } 
} 

何の循環依存関係は生じないだろうので、あなたが唯一のインタフェースで、引数の順方向として主に使用しているので、あなたは、CPPでの実装とああファイル内のインタフェースを定義します宣言すれば十分だろう。

//worker.h 
class mainthread; 

class Worker {  
    void doWork(void * mainthread); 
} 

//worker.cpp 
#include "main.h" 
void Worker::doWork(/* and so on*/} 


//main.h 
class Main{ 

    atomi_int filesfound; 

    void main_part(); 

    void callbackwithinformation(int updatedcount); 
} 

//main.cpp 
//no need for worker.h here 
void Main::main_part() /* implementation and so on */ 
+0

この例をありがとう。なぜjoin()がそんなに重要なのですか?しかし、WorkerMainは、異なる.hクラスファイルによって定義されています。しかし、彼らは私たちが知っているように互いを含めることはできません。何かヒントはありますか? – Benjamin

関連する問題