【问题标题】:Getting return value from a boost::threaded member function?从 boost::threaded 成员函数中获取返回值?
【发布时间】:2010-12-15 08:26:20
【问题描述】:

我有一个像下面这样的工人阶级:

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

它打算与 boost::thread 和 boost::bind 一起执行,例如:

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

我的问题是,如何获得 Worker::Do 的返回值?

提前致谢。

【问题讨论】:

    标签: c++ boost boost-thread boost-bind boost-function


    【解决方案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.
    

    如果你可以使用 c++0x,那么使用 std::async 将打包以上所有内容并执行以下操作:

    std::future<int> f = std::async( std::bind(&Worker::Do, &worker) );
    int retval = f.get(); //Will block until do returns an int.
    

    【讨论】:

      【解决方案2】:

      我不认为你可以得到返回值。

      相反,您可以将值存储为 Worker 的成员:

      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
      

      【讨论】:

      • 谢谢,我想我必须重新设计一下。
      【解决方案3】:

      此外,您还有一些对 boost::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));
      

      您可以这样做,因为 Thread 的构造函数是内部 bind() 调用的便捷包装器。 Thread Constructor with arguments

      【讨论】:

      • 这看起来很简单。谢谢,但我的实际实现包含许多成员函数,所以我不能真正使用 () 运算符。
      • @何世明:不用bind()还是可以用的。例如, boost::thread(worker(),&Worker::Do) (语法可能略有偏差,因为它是我的头顶)。
      【解决方案4】:
      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”的概念,参考这个link

      【讨论】:

        【解决方案5】:

        另一个选择是使用Boost.Lambda 库。然后可以在不改变Worker类的情况下编写如下代码:

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

        当您无法更改要调用的函数时,这尤其有用。像这样,返回值被包裹在一个局部变量ret中。

        【讨论】:

        • 这将在当前线程中执行worker.Do(),将结果复制到一个lambda对象中,在新线程上运行该lambda(从而将worker.Do()的结果分配给ret),然后然后等待新线程的执行完成。这很可能不是期望的行为,因为它在错误的线程中执行worker.Do()。从在不同线程中执行的函数返回结果的最简单正确方法是使用期货和承诺。
        猜你喜欢
        • 2019-06-26
        • 1970-01-01
        • 1970-01-01
        • 2014-12-13
        • 2019-12-14
        • 2016-01-07
        • 1970-01-01
        • 2015-05-24
        • 1970-01-01
        相关资源
        最近更新 更多