无论如何要从 std::thread 获取返回码?我有一个返回整数的函数,我希望能够在线程完成执行时从函数中获取返回码。
4 回答
不,这不是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();
您可以使用(零超时)的wait_for
成员函数f
来查看结果是否准备好。
正如其他人所建议的那样,<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
Kerrek SB 的回答是正确的,但我建议添加另一个示例(他建议应该是一个答案,所以在这里)。
我最近发现,至少在 VC11 中,std::async
直到应用程序结束才会释放线程的所有资源,从而可能导致内存泄漏误报(如果您正在使用例如 Visual Leak Detector 监视它们)。
在这里我的意思是,在大多数基本应用程序中,不值得看这个答案的其余部分,但如果像我一样,你需要检查内存泄漏并且不能让误报,比如静态数据在结束时没有发布主功能。如果是您的情况,那么这可能会有所帮助。
std::async
默认情况下不保证在单独的线程中运行,仅当您std::launch::async
用作第一个参数时。否则由实现决定做什么,这就是为什么 VC11 实现将使用新的 Microsoft 并发运行时任务管理器将提供的功能作为推送到任务池中的任务来管理,这意味着以透明的方式维护和管理线程。有一些方法可以显式终止任务管理器,但这太特定于平台,当您想要 1)确保启动一个线程并且 2)稍后获得结果和 3)确保线程完全释放时,异步是一个糟糕的选择你得到结果。
完全做到这一点的替代方法是使用std::packaged_task
并std::thread
与std::future
. 它的完成方式几乎与 using 相似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::promise
与未来相关联的对象。std::packaged_task
主要像以下的增强版本一样工作std::function
:
现在我们需要显式地执行线程:
std::thread thread(std::move(task));
thread.detach();
移动是必要的,因为std::packaged_task
不可复制。仅当您只想使用未来进行同步时才需要分离线程 - 否则您将需要显式加入线程。如果你不这样做,当线程的析构函数被调用时,它只会调用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;
}