0

我正在尝试将我的类实例传递给线程并从线程返回处理后的对象。我在谷歌上搜索了 C++ 多线程,发现 std::promising 可能会有所帮助。

但是,我一开始就被困住了。这是我的代码:

void callerFunc()
{
    //...
    std::promise<DataWareHouse> data_chunks;    
    // DataWareHouse is my customized class
    //data_chunks has a vector<vector<double>> member variable
    std::thread(&run_thread,data_chunks);
    // ............
}

void run_thread(std::promise<DataWareHouse> data_chunks)
{
    // ... 
    vector<vector<double>> results;
    // ...
    data_chunks.set_value(results);
}

上面的代码会产生错误:

 `error C2248: 'std::promise<_Ty>::promise' : cannot access private member declared in class 'std::promise<_Ty>'`

我可以知道我错了什么以及如何解决吗?

非常感谢。:-)

4

4 回答 4

3

您的第一个问题是您正在使用std::thread--std::thread是一个低级类,您应该在其上构建更高的抽象。线程是 C++11 中的 C++ 新标准化的,所有粗糙的部分还没有归档。

在 C++11 中使用线程的三种不同模式可能对您有用。

首先,std::async。二、std::thread混杂std::packaged_taskstd::thread第三,处理std::promise原始数据。

我将说明第三个,它是最低级别且最危险的,因为这是您所要求的。我建议查看前两个选项。

#include <future>
#include <vector>
#include <iostream>

typedef std::vector<double> DataWareHouse;

void run_thread(std::promise<DataWareHouse> data_chunks)
{
  DataWareHouse results;
  results.push_back( 3.14159 );
  data_chunks.set_value(results);
}

std::future<DataWareHouse> do_async_work()
{
  std::promise<DataWareHouse> data_chunks;  
  std::future<DataWareHouse> retval = data_chunks.get_future();
  // DataWareHouse is my customized class
  //data_chunks has a vector<vector<double>> member variable
  std::thread t = std::thread(&run_thread,std::move(data_chunks));
  t.detach(); // do this or seg fault
  return retval;
}

int main() {
  std::future<DataWareHouse> result = do_async_work();
  DataWareHouse vec = result.get(); // block and get the data
  for (double d: vec) {
    std::cout << d << "\n";
  }
}

活生生的例子

使用std::async,您将有一个函数返回DataWareHouse,它会std::future<DataWareHouse>直接返回 a 。

使用std::packaged_task<>,它会将您的run_thread并将其转换为packaged_task可以执行的,并std::future从中提取。

于 2013-08-14T13:23:52.693 回答
2

std::promise<>是不可复制的,并且在调用run_thread()时您正在隐式尝试调用复制构造函数。错误消息告诉您不能使用复制构造函数,因为它被标记为私有。

您需要通过引用 ( std::promise<DataWareHouse> &) 传递承诺。callerFunc()如果保证在对象完成之前不返回,这是安全run_thread()的(否则您将使用对已销毁堆栈分配对象的引用,我不必解释为什么这样做不好)。

于 2013-08-13T15:20:27.947 回答
2

您正在尝试按值将承诺传递给线程;但是您需要通过引用传递以将结果返回给调用者的承诺。std::promise是不可复制的,以防止此错误。

std::thread(&run_thread,std::ref(data_chunks));
                        ^^^^^^^^

void run_thread(std::promise<DataWareHouse> & data_chunks)
                                            ^
于 2013-08-13T15:22:29.370 回答
1

错误告诉您无法复制std::promise,您可以在此处执行此操作:

void run_thread(std::promise<DataWareHouse> data_chunks)

和这里:

std::thread(&run_thread,data_chunks); // makes copy of data_chunks

你应该传递一个参考:

void run_thread(std::promise<DataWareHouse>& data_chunks);
//                                         ^

然后将 an 传递std::reference_wrapper给线程,否则它也会尝试复制 Promise。这很容易做到std::ref

std::thread(&run_thread, std::ref(data_chunks));
//                       ^^^^^^^^

显然data_chunks在线程完成运行之前必须处于活动状态,因此您必须将线程加入callerFunc().

于 2013-08-13T15:21:40.510 回答