C++ 生成多个线程,每个线程返回多个值
我正在尝试生成多个线程来执行给定的任务。此任务根据传入的内容而有所不同,并将返回多个值 我尝试了以下几点,但都没有成功:C++ 生成多个线程,每个线程返回多个值,c++,multithreading,c++11,stdthread,C++,Multithreading,C++11,Stdthread,我正在尝试生成多个线程来执行给定的任务。此任务根据传入的内容而有所不同,并将返回多个值 我尝试了以下几点,但都没有成功: std::vector<std::tuple<std::thread, Task, Result1, Result2>> workers; for (auto const& task : tasks) { Result1 result1; Result2 result2; std::tuple<std::threa
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;
}
执行输出:
任务=A结果1=A1结果2=A2
任务=B结果1=B1结果2=B2
任务=C结果1=C1结果2=C2
线程不可复制构造,因此错误'thread(constthread&)'是私有的
线程是可构造移动的,因此您可以使用std::move向后放置一个右值引用:
workers.emplace_back(std::move(worker));
虽然这将解决眼前的问题,但请注意,您有一个更大、更险恶的问题,即悬空引用
您正在向线程函数传递对临时变量的引用(然后创建一个元组,其中包含Result1
和Result2
的副本)
现在,您不必尝试使用结果变量创建元组,并将引用传递给线程元组成员。底部循环中的t
s应该是w
s,对吗?另外,不要害怕使用结构或类。一个由4项组成的元组急需名称。请编辑您的问题,以包含您可能看到的任何错误消息。请尝试提供一个最小的、可编译的、可验证的示例,以及对预期行为和实际观察到的行为的描述。调用workers.emplace_back(std::move(worker))
适用于MSVC 2015。你在用什么编译器?你说得很好。我相信我在编写一个可编译的代码示例时解决了其中一些问题。看看我添加到问题中的代码,我真的建议你接受OOD,并将你的工人封装到工人类中。这将使您的代码更容易推理。为了确保结果对象的生命周期比您的循环更长,您也不一定需要使其成为指针。创建工作人员将非常简单-工作人员代码>-完成。我仍在考虑您关于重构代码以改进封装的建议。我主要的犹豫是创建一个只在这种特定情况下使用的类,但也许这是正确的方法。@Snooze为什么不创建一个类呢?您正在将“完成工作”所需的所有内容封装到一个“worker”类中。明天我将尝试这种方法,看看结果如何。问题中的代码示例只是一个微不足道的示例,因为我无法共享原始代码。希望重构能消除我在AOSP上看到的编译器错误。谢谢你的反馈!
workers.emplace_back(std::move(worker));
Result1 result1;
Result2 result2;
std::tuple<std::thread, Task, Result1, Result2> worker =
std::make_tuple(
std::thread(
&Slave::performTask,
this,
task,
std::ref(result1), <-- here you pass a reference to a local variable
std::ref(result2)), <--
task,
result1, <-- here you copy construct the tuple member from a local var
result2); <--
struct Worker
{
Worker(Task& task)
: task(task)
, _thread(&Worker::performTask, this)
{
}
void performTask()
{
result1 = task.foo();
result2 = task.bar();
}
void join()
{
_thread.join();
}
Task task;
Result1 result1;
Result2 result2;
private:
std::thread _thread;
};