【问题标题】:How to get a return value from a thread?如何从线程中获取返回值?
【发布时间】:2019-09-06 06:31:14
【问题描述】:

让我们说一个函数,

int fun(){
    static int a = 10;
    a = a+1;
    return a;
}

上面的函数返回一个整数值,

//Without thread obtaining return value
#include<iostream>
int main()
{
    int var = 0;
    var = fun();
    std::cout << "The value " << value << std::endl;
    return 0;
}

现在有什么方法可以在C++11线程调用时获取返回值,

//Using thread
#include<iostream>
#include<thread>
int main()
{
    std::thread t1(fun);//Invoking thread
    //How to obtain the return value of the thread ?
    return 0;
}

谢谢!

【问题讨论】:

  • int return_of_t1; std::thread t1([&amp;return_of_t1]{return_of_t1 = fun();});
  • 顺便说一句,从不同线程调用fun会导致最终混乱。
  • 好的,我们可以使用 lambda 函数,我想我们可以通过使用锁定机制来避免混乱。
  • std::async 被设计用来做这样的工作。

标签: c++ multithreading c++11


【解决方案1】:

为了从打算在后台运行的函数中获取返回值,您可能需要考虑使用std::future 而不是直接创建std::thread 对象。您可以使用std::async() 函数模板来启动一个异步 任务。它返回一个std::future 对象,该对象最终将包含所传递函数的返回值:

auto res = std::async(fun);

// ... optionally do something else

std::cout << res.get() << '\n';

也就是说,您通过调用std::async(func) 创建一个std::future&lt;int&gt;。然后,当您需要fun() 的返回值时,您只需在future 上调用get() 成员函数即可。如果未来还没有准备好(即,如果它还没有结果),那么线程将阻塞直到它准备好。


为什么不直接使用std::thread

std::thread 的问题在于它没有提供直接的机制来传输在其构造中传递的可调用对象的返回值。例如,假设您要使用std::thread 启动一个新线程,以使用以下函数计算两个整数的和:

int sum(int a, int b) { return a + b; }

你可能会尝试的是:

std::thread th_sum(sum, 1, 2);

// ... optionally do something else

th_sum.join();
// calculation is finished, but where is the result?

th_sum 表示的线程确实计算了 12 的总和。但是,您不会从关联的 std::thread 对象中获得 sum() 的返回值,即结果。

相反,您可以做些什么来处理这个缺陷,例如,为sum() 创建一个包装函数,该函数有一个 out 参数 作为结果而不是返回它:

void sum_outparam(int a, int b, int& res) { res = sum(a, b); }

然后,您可以启动一个新线程来运行此包装函数,并在std::ref() 的帮助下,您将在res 中获得结果:

int res;
std::thread th_sum(sum_outparam, 1, 2, std::ref(res));

// ... optionally do something else


th_sum.join();
// now, res contains the result

【讨论】:

    【解决方案2】:

    您可以使用async,承诺的未来(双关语)或打包的任务。

    // future from a packaged_task
    std::packaged_task<int()> task(fun); // wrap the function
    std::future<int> f1 = task.get_future();  // get a future
    std::thread(std::move(task)).detach(); // launch on a thread
    
    // future from an async()
    std::future<int> f2 = std::async(std::launch::async, fun);
    
    // future from a promise
    std::promise<int> p;
    std::future<int> f3 = p.get_future();
    std::thread( [](std::promise<int>& p){ p.set_value(fun()); },
                 std::ref(p) ).detach();
    
    
    std::cout << "Waiting...";
    f1.wait();
    f2.wait();
    f3.wait();
    std::cout << "Done!\nResults are: "
              << f1.get() << ' ' << f2.get() << ' ' << f3.get() << '\n';
    

    【讨论】:

      【解决方案3】:

      不,std::thread 只是一个简单的 C++ 包装器,它允许启动 OS 执行线程并等待它完成。

      要与调用线程共享返回值,您可以手动为线程提供共享状态,或使用更高级别的工具,如packaged_taskfuture 等。

      【讨论】:

        猜你喜欢
        • 2020-11-09
        • 2011-10-17
        • 2018-04-15
        • 1970-01-01
        • 2011-10-29
        • 2018-10-21
        相关资源
        最近更新 更多