我正在使用 vc2011,结果发现 std::async(std::launch::async, ... ) 有点错误(有时它不会产生新线程并并行运行它们,而是重用线程和一个接一个地运行任务)。当我进行昂贵的网络调用时,这太慢了。所以我想我会编写自己的异步函数。我被卡住了,std::promise 应该在哪里生活?在 1) 线程函数、2) 异步函数或 3) 调用函数中。
代码:
#include <future>
#include <thread>
#include <iostream>
#include <string>
#include <vector>
std::string thFun() {
throw std::exception("bang!");
return "val";
}
std::future<std::string> myasync(std::promise<std::string>& prms) {
//std::future<std::string> myasync() {
//std::promise<std::string> prms; //needs to outlive thread. How?
std::future<std::string> fut = prms.get_future();
std::thread th([&](){
//std::promise<std::string> prms; //need to return a future before...
try {
std::string val = thFun();
prms.set_value(val);
} catch(...) {
prms.set_exception(std::current_exception());
}
});
th.detach();
return fut;
}
int main() {
std::promise<std::string> prms; //I really want the promise hidden iway in the myasync func and not live here in caller code but the promise needs to outlive myasync and live as long as the thread. How do I do this?
auto fut = myasync(prms);
//auto fut = myasync(); //Exception: future already retrieved
try {
auto res = fut.get();
std::cout << "Result: " << res << std::endl;
} catch(const std::exception& exc) {
std::cout << "Exception: " << exc.what() << std::endl;
}
}
我似乎无法理解 std::promise 需要比 async 函数寿命更长(并且与线程一样长)的事实,因此 promise 不能作为 async func 中的局部变量存在。但是 std::promise 也不应该存在于调用者代码中,因为调用者只需要了解期货。而且我不知道如何在线程函数中实现承诺,因为异步需要在调用线程函数之前返回一个未来。我在这个问题上摸不着头脑。
有人有什么想法吗?
编辑:我在这里强调这一点,因为顶部评论有点误导。虽然允许 std::asycn 的默认值是 dererred 模式,但当显式设置 std::launch::async 的启动策略时,它必须表现得“好像”线程立即产生并运行(参见 en 中的措辞.cppreference.com/w/cpp/thread/async)。请参阅 pastebin.com/5dWCjjNY 中的示例,以了解这不是 vs20011 中所见行为的一种情况。该解决方案效果很好,并将我的实际应用程序加速了 10 倍。
编辑 2:MS 修复了这个错误。更多信息在这里:https ://connect.microsoft.com/VisualStudio/feedback/details/735731/std-async-std-launch-async-does-not-behave-as-std-thread