【发布时间】:2017-01-23 22:58:38
【问题描述】:
我正在尝试生成将执行给定任务的多个线程。此任务根据传入的内容而有所不同,并将返回多个值。
我尝试了以下几行但没有运气:
std::vector<std::tuple<std::thread, Task, Result1, Result2>> workers;
for (auto const& task : tasks) {
Result1 result1;
Result2 result2;
std::tuple<std::thread, Task, Result1, Result2> worker = std::make_tuple(std::thread(&Slave::performTask, this, task, std::ref(result1), std::ref(result2)), task, result1, result2);
workers.emplace_back(worker);
}
for (auto& w : workers) {
std::get<0>(w).join();
std::cout << "Task=" << std::get<1>(w) << " Result1=" << std::get<2>(w) << " Result2=" << std::get<3>(w) << std::endl;
}
我认为问题在于在嵌套容器中引用 std::thread 导致 workers.emplace_back(worker); 无效。我尝试在几个地方使用 std::move 没有成功。
workers.emplace_back(worker); 导致以下错误:
external/libcxx/include/thread:268:5: 错误:'std::__1::thread::thread(const std::__1::thread&)' 是私有的 线程(常量线程&);
external/libcxx/include/type_traits:887:87: 错误:在此上下文中 sizeof(__is_convertible_imp::__test<_t2>(__is_convertible_imp::__source<_t1>())) == 1
external/libcxx/include/type_traits:851:28: 错误:初始化 'char std::__1::__is_convertible_imp::__test(_Tp) [with _Tp = std::__1::thread]' 的参数 1 模板字符 __test(_Tp);
按照 Daniel 的要求,我整理了一个最小的可编译示例。它在 cpp.sh 上正确编译和执行:
#include <iostream>
#include <thread>
#include <tuple>
#include <vector>
using Task = std::string;
using Result1 = std::string;
using Result2 = std::string;
class Slave {
private:
void performTask(Task task, Result1& result1, Result2& result2) {
if (task == "A") {
result1 = "A1";
result2 = "A2";
} else if (task == "B") {
result1 = "B1";
result2 = "B2";
} else {
result1 = "C1";
result2 = "C2";
}
}
public:
std::vector<Task> tasks;
std::vector<std::tuple<Task, Result1, Result2>> performParallel() {
std::vector<std::tuple<Task, Result1, Result2>> results;
std::vector<std::tuple<std::thread, Task, std::unique_ptr<Result1>, std::unique_ptr<Result2>>> workers;
for (auto const& task : tasks) {
std::unique_ptr<Result1> result1(new Result1);
std::unique_ptr<Result2> result2(new Result2);
std::tuple<std::thread, Task, std::unique_ptr<Result1>, std::unique_ptr<Result2>> worker = std::make_tuple(std::move(std::thread(&Slave::performTask, this, task, std::ref(*result1), std::ref(*result2))), task, std::move(result1), std::move(result2));
workers.emplace_back(std::move(worker));
}
for (auto& w : workers) {
std::get<0>(w).join();
std::tuple<Task, Result1, Result2> result = std::make_tuple(std::get<1>(w), *std::get<2>(w), *std::get<3>(w));
results.emplace_back(result);
}
return results;
}
};
int main() {
Slave slave;
slave.tasks = { "A", "B", "C" };
std::vector<std::tuple<Task, Result1, Result2>> results = slave.performParallel();
for (auto const& r : results) {
std::cout << "Task=" << std::get<0>(r) << " Result1=" << std::get<1>(r) << " Result2=" << std::get<2>(r) << std::endl;
}
}
执行输出:
任务=A 结果1=A1 结果2=A2
任务=B 结果1=B1 结果2=B2
任务=C 结果1=C1 结果2=C2
【问题讨论】:
-
底部循环中的
ts 应该是ws 对吧? -
另外,不要害怕使用结构或类。包含 4 个项目的元组急需名称。
-
请编辑您的问题以包含您可能看到的任何错误消息。
-
请尝试提供一个最小的、可编译的、可验证的示例以及对预期行为和实际观察到的行为的描述。
-
调用
workers.emplace_back(std::move(worker))适用于 MSVC 2015。您使用的是什么编译器?
标签: c++ multithreading c++11 stdthread