可能是重复问题:
C++:如何从std::thread中简单返回值?
有没有办法从std::thread中获取返回值?我有一个返回整数的函数,当线程执行完成后,我想能够获取该函数的返回值。
可能是重复问题:
C++:如何从std::thread中简单返回值?
有没有办法从std::thread中获取返回值?我有一个返回整数的函数,当线程执行完成后,我想能够获取该函数的返回值。
不,那不是 std::thread
的用途。
相反,使用 async
来获得一个 future
:
#include <future>
int myfun(double, char, bool);
auto f = std::async(myfun, arg1, arg2, arg3); // f is a std::future<int>
// ...
int res = f.get();
你可以使用 f
的 wait_for
成员函数(超时时间为零)来查看结果是否准备好。正如其他人所建议的,可以使用<future>
中的设施来实现此目的。然而,我反对以下答案:
不,您无法使用
std::thread
完成这项任务。
以下是使用std::thread
实现您想要的一种方式。这绝不是唯一的方法:
#include <thread>
#include <iostream>
int func(int x)
{
return x+1;
}
int main()
{
int i;
std::thread t([&] {i = func(2);});
t.join();
std::cout << i << '\n';
}
3
thread
对象中获取它;你是因为创建了一个使用引用来检索变量的函数对象。任何人都可以这样做;问题是如何捕获thread
对象的返回值。 - Nicol Bolasstd::thread
的返回值”...相反,你有一种类似于“packaged_task”的穷人版,我想。但这肯定是一个非常有用的观察。(顺便说一句,第二个句子不是一个问题;-)。) - Kerrek SBstd::async
不会释放线程的所有资源,直到应用程序结束,这可能会导致 内存泄漏误报(如果您正在使用 Visual Leak Detector 等监视它们)。在此,我指的是在大多数基本应用程序中,不值得查看本答案的其余部分,但是如果像我一样需要检查内存泄漏并且不能容忍假阳性,例如在 main 函数结束时未释放静态数据。 如果是这种情况,则这可能有所帮助。
std::async
默认情况下不能保证在单独的线程中运行,只有当您使用std::launch::async
作为第一个参数时才会这样。否则,实现会决定要做什么,这就是为什么VC11实现将使用新的Microsoft Concurrency Runtime任务管理器将提供的函数作为推入任务池的任务来管理,这意味着线程以透明的方式进行维护和管理。有一些方法可以显式地终止任务管理器,但这太具体于平台,使得async在以下情况下不是很好的选择:1)确保启动一个线程并且2)稍后获得结果并且3)确保在线程释放结果时完全释放线程。
实现这一点的替代方法是使用std::packaged_task
和std::thread
与std::future
结合使用。它的实现方式几乎类似于使用std::async
,只是稍微冗长一些(这意味着您可以将其泛化为自定义模板函数,如果您想要的话)。
#include <packaged_task>
#include <thread>
int myfun(double, char, bool);
std::packaged_task<int(double, char, bool)> task(myfun, arg1, arg2, arg3);
auto f = task.get_future(); // f is a std::future<int>
std::thread thread(std::move(task));
thread.detach();
std::packaged_task
不能被复制。如果你只想使用future进行同步,那么分离线程是必要的 - 否则你需要显式地加入线程。如果不这样做,在线程的析构函数被调用时,它将会调用std::terminate()
。// ...
int res = f.get(); // Synchronization and retrieval.
packaged_task
的示例:#include <future>
#include <iostream>
void task_waiter(std::future<int>&& f) {
std::future<int> ft = std::move(f);
int result = ft.get();
std::cout << result << '\n';
}
int the_task() {
return 17;
}
int main() {
std::packaged_task<int()> task(the_task);
std::thread thr(task_waiter, task.get_future());
task();
thr.join();
return 0;
}
packaged_task
对象获取一个future
对象,然后将packaged_task
对象传递给运行任务的新线程。 - Pete Becker
packaged_task
不是很了解,也不知道它的习惯用法。请您将其发布为答案; 这对每个人都有好处。 - Kerrek SBwait_for
和零超时来检查是否准备就绪。 - Anthony Williamsasync
的future并立即调用get
。这个想法是,你有其他事情要做,只有在绝对需要结果时才会阻塞。 - Kerrek SB