何时使用async或packaged_task的承诺?

时间:2013-07-18 17:12:22

标签: c++ asynchronous promise future packaged-task

我应该何时std::promise使用std::asyncstd::packaged_task? 你能告诉我何时使用它们的实际例子吗?

2 个答案:

答案 0 :(得分:43)

的std ::异步

std::async是获得std::future的简洁方法,但是:

  • 并不总是会启动新线程;将std::launch::async作为第一个参数来强制它。

    auto f = std::async( std::launch::async, func );
    
  • std::~future析构函数可以阻止,直到新线程完成

    auto sleep = [](int s) { std::this_thread::sleep_for(std::chrono::seconds(s)); };
    
    {
        auto f = std::async( std::launch::async, sleep, 5 );
    }
    

    通常我们希望只有.get().wait()块,但对于从std::future返回的std::async,析构函数也可能会阻塞,所以请注意不要阻止主线只是忘了它。

  • 如果std::future存储在临时生活对象中,std::async调用将立即停止,因此如果您有以下数据块 10秒删除auto f =初始化:

    auto sleep = [](int s) { std::this_thread::sleep_for(std::chrono::seconds(s)); };
    
    {
        auto f1 = std::async( std::launch::async, sleep, 5 );
        auto f2 = std::async( std::launch::async, sleep, 5 );
    }
    

的std :: packaged_task

std::packaged_task本身与线程无关:它只是一个仿函数和一个相关的std::future。请考虑以下事项:

auto task = [](int i) { std::this_thread::sleep_for(std::chrono::seconds(5)); return i+100; };

std::packaged_task< int(int) > package{ task };
std::future<int> f = package.get_future();
package(1);
std::cout << f.get() << "\n";

此处我们只是按package(1)运行任务,在它返回后,f已就绪,因此.get()上没有阻止。

std::packaged_task的一个特性使它对线程非常有用。您可以使用std::thread初始化std::packaged_task,而不仅仅是一个函数,它提供了一种非常好的方式来访问&#39; std :: future&#39;。请考虑以下事项:

std::packaged_task< int(int) > package{ task };
std::future<int> f = package.get_future();
std::thread t { std::move(package), 5 };

std::cout << f.get() << "\n";       //block here until t finishes

t.join();

由于std::packaged_task不可复制,因此您必须将其移至std::move的新主题。

的std ::诺

std::promise是一种强大的机制。例如,您可以将值传递给新线程,而无需任何其他同步。

auto task = [](std::future<int> i) {
    std::cout << i.get() << std::flush;
};

std::promise<int> p;
std::thread t{ task, p.get_future() };

std::this_thread::sleep_for(std::chrono::seconds(5));
p.set_value(5);

t.join();

新主题会在.get()

上等待我们

所以,一般来说,回答你的问题:

  • 仅将std::async用于简单的事情,例如打一些非阻塞的电话,但要记住上面阻止的评论。
  • 使用std::packaged_task轻松访问std::future,并将其作为单独的帖子运行

    std::thread{ std::move(package), param }.detach();
    

    std::thread t { std::move(package), param };
    
  • 当您需要对未来进行更多控制时,请使用std::promise

另请参阅std::shared_future以及在线程std::promise::set_exception

之间传递异常

答案 1 :(得分:-1)

承诺用于存储使用例如计算的值。一个std :: async。 见http://en.cppreference.com/w/cpp/thread/promise

我可以想象你想知道std :: packaged_task和std :: async之间的区别(在最常见的方法中,std :: async启动一个单独的线程来运行函数/ lambda / etc,可能)计算。 std :: packaged_task用于使用参数的当前值包装函数/ lambda / etc,以便您可以同步或在单独的线程中运行它。

std :: packaged_task和std :: async都提供了一个std :: future,它将在运行后包含包装函数/ lambda / etc的RESULT。 在内部,std :: future使用std :: promise来保存该结果。