2009-11-11 7 views
6

私は以下のような労働者のクラスを持っている:::ブーストで実行されることを意図していますboost :: threadedメンバ関数から戻り値を取得していますか?

class Worker{ 
public: 
    int Do(){ 
    int ret = 100; 
    // do stuff 
    return ret; 
    } 
} 

スレッドとブースト::バインドを、のように:私の質問はどのように行う、ある

Worker worker; 
boost::function<int()> th_func = boost::bind(&Worker::Do, &worker); 
boost::thread th(th_func); 
th.join(); 

私はWorker :: Doの戻り値を取得しますか?

ありがとうございます。

答えて

7

私はあなたが戻り値を得ることはできないと思います。

代わりに、労働者の一員として値を格納することができます

class Worker{ 
public: 
    void Do(){ 
    int ret = 100; 
    // do stuff 
    m_ReturnValue = ret; 
    } 
    int m_ReturnValue; 
} 

そしてそうのようにそれを使用します。

Worker worker; 
boost::function<void()> th_func = boost::bind(&Worker::Do, &worker); 
boost::thread th(th_func); 
th.join(); 
//do something with worker.m_ReturnValue 
+0

ありがとう、私は少し再設計しなければならないと思う。 –

2

また、あなたも後押しするために、いくつかの冗長な呼び出しを持っている:: bind()とboost :: function()です。代わりに、次のようにすることができます。

class Worker{ 
    public: 
     void operator(){ 
      int ret = 100; 
      // do stuff 
      m_ReturnValue = ret; 
     } 
    int m_ReturnValue; 
} 

Worker worker; 
boost::thread th(worker());//or boost::thread th(boost::ref(worker)); 

これは、スレッドのコンストラクターが内部のbind()呼び出しの便利なラッパーであるために実行できます。 Thread Constructor with arguments

+0

それはかなり簡単に見えます。ありがとうが、実際の実装には多くのメンバー関数が含まれているので、実際には()演算子を使用することはできません。 –

+0

@ He Shiming:bind()を使わなくてもそれを使えます。たとえば、boost :: thread(worker()、&Worker :: Do)(構文は頭の上から少し離れているかもしれません)。 –

-2

もう1つのオプションは、Boost.Lambdaライブラリを使用しています。 Workerクラスを変更することなく、次のようにあなたがコードを書くことができます:あなたが呼び出すための機能を変更することはできませんとき

Worker worker; 
int ret; 
boost::thread th(boost::lambda::var(ret) = worker.Do()); 
th.join(); 

これは特に便利です。このように、戻り値はローカル変数retにラップされます。

+4

これは、現在のスレッドで 'worker.Do()'を実行し、結果をラムダオブジェクトにコピーし、新しいスレッドでそのラムダを実行します(したがって、 'worker'の結果を' ret'に割り当てます)新しいスレッドの実行が完了するのを待ちます。間違ったスレッドで 'worker.Do()'を実行するので、これはおそらく**望ましい動作ではありません**。異なるスレッドで実行される関数から結果を返す最も簡単な正しい方法は、先物と約定を使用することです。 – Mankarse

13

もう1つのオプションは約束/先物を使用することです。

class Worker{ 
public: 
    void Do(boost::promise<int> & p){ 
    int ret = 100; 
    // do stuff 
    p.set_value(ret); 
    } 
}; 
//Later... 
boost::promise<int> p; 
boost::thread t(boost::bind(&Worker::Do, &worker, boost::ref(p)); 
int retval = p.get_future().get(); //This will block until the promise is set. 

そして、あなたはその後、STDを使用してC++ 0xを、使用できるかどうか::非同期は、上記のすべてをパッケージ化し、ちょうど行います

std::future<int> f = std::async(std::bind(&Worker::Do, &worker)); 
int retval = f.get(); //Will block until do returns an int. 
1
class Worker{ 
public: 
    int Do(){ 
    int ret = 100; 
    // do stuff 
    return ret; 
    } 
} 

Worker worker; 
boost::packaged_task<int> ptask(boost::bind(&Worker::Do, &worker)); 
boost::unique_future<int> future_int = ptask.get_future(); 
boost::thread th(boost::move(ptask)); 
th.join(); 
if (future_int.is_ready()) 
    int return_value = future_int.get(); 

あなたが見てみることができ"boost :: future"コンセプト、ref link

関連する問題