如何在 c++ 中使用 future 和 promise 从函数线程中获取返回值

How to get return value from function thread using future and promise in c++

本文关键字:函数 promise 线程 返回值 获取 future c++      更新时间:2023-10-16

我有一个下面的代码,我正在使用futurepromise从函数中获取返回值。下面是代码:

void myfunction2(string msg, std::promise<std::string> && prms)
{
    prms.set_value(msg);
}
int main()
{
    std::promise<std::string> prms;
    std::future<std::string> ftr = prms.get_future();
    while (1)
    {
        thread t1(myfunction2, "Hello thread", std::move(prms));
        cout << "Main loop" << endl;
        std::string str = ftr.get();
        std::cout << str << std::endl;
        t1.join();
        Sleep(2000);
    }
}

它输出如下:

Main loop
Hello thread
Main loop

因为它在 while(1( 内部,所以当控件回到 std::string str = ftr.get(); 时,它会抛出一些异常

Unhandled exception at 0x00007FFDD0F1A388 in Testcode.exe: Microsoft C++ exception: std::future_error at memory location 0x00000003FDCFF740.

如果我在没有 while(1( 的情况下运行它,这将起作用,但我实际上需要在 'while(1( 循环中运行它。如何解决此问题。

您只能设置一次承诺的值。要在程序中使用 loop,请将 promise 和 future 变量降级到循环范围内,如下所示:

int main()
{
    int i = 0;
    while (1)
    {
        std::promise<std::string> prms;
        std::future<std::string> ftr = prms.get_future();
        thread t1(myfunction2, "Hello thread", std::move(prms));
        cout << "Main loop" << endl;
        std::string str = ftr.get();
        std::cout << str << std::endl;
        t1.join();
        Sleep(2000);
        if (++i > 3) break; // no infinite loop
    }
}

已编辑:在您的代码中,其他线程在第一个线程加入之前不会生成,依此类推。编辑代码片段以允许并发执行。在这里,所有线程都生成以允许并行执行,然后在最后共同加入。

int main()
{
    std::vector<std::pair<std::thread, std::future<std::string>>> threads;
    for (int i = 0; i < 5; i++)
    {
        std::promise<std::string> prms;
        std::future<std::string> fut = prms.get_future();
        thread th(myfunction2, "Hello thread", std::move(prms));
        threads.push_back(make_pair(move(th), move(fut)));
    }
    for (auto& e : threads)
    {
        auto th = move(e.first);
        auto fut = move(e.second);
        std::string str = fut.get();
        std::cout << str << std::endl;
        th.join();
    }    
}

根据: https://en.cppreference.com/w/cpp/thread/promise/set_value

如果没有共享状态

共享状态,则会引发异常 已存储值或异常。

使用您的代码,您似乎正在尝试在承诺中存储多个值。其次,正如 Quimby 所指出的,在第二次迭代中,传递的承诺已经被移出,因此没有共享状态(请参阅有关移动 ctor 的文档以获取std::promise https://en.cppreference.com/w/cpp/thread/promise/promise(。对我来说,目前还不清楚你想实现什么。无论如何,请记住,std::promisestd::future基本上是一次性通信通道,共享状态只能设置一次。

我重写了您的代码以允许它运行,为每次迭代创建一个新的promise/future对。

#include <future>
#include <iostream>
#include <thread>
#include <chrono>
#include <string>

void myfunction2(std::string msg, std::promise<std::string> && prms)
{
    prms.set_value(msg);
}
int main()
{
    while (1)
    {
        std::promise<std::string> prms;
        std::future<std::string> ftr = prms.get_future();
        thread t1(myfunction2, "Hello thread", std::move(prms));
        cout << "Main loop" << endl;
        std::string str = ftr.get();
        std::cout << str << std::endl;
        t1.join();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}