【问题标题】:Asynchronous HTTP requests with co_await带有 co_await 的异步 HTTP 请求
【发布时间】:2021-01-18 09:04:02
【问题描述】:

我有多个std::functions 在我的应用程序的主线程(而不是不同的线程)上调用(作为异步 HTTP 请求的结果),例如:

namespace model { struct Order{}; struct Trade{};}

std::function<void (std::string)> func1 = [](std::string http_answer)
{
    std::vector<model::Order> orders = ParseOrders(http_answer);
    std::cout << "Fetched " << orders.size() << " open/closed orders.");
}

std::function<void (std::string)> func2 = [](std::string http_answer)
{
    std::vector<model::Trade> trades = ParseTrades(http_answer);
    std::cout << "Fetched " << trades.size() << " trades.");
}

func1func2 都解析了HTTP 答案时,如何调用process_result

auto process_result = [](std::vector<model::Order> orders, std::vector<model::Trades> trades)
{
    std::cout << "Matching orders and trades.";
};

co_await 或类似的解决方案吗?

【问题讨论】:

  • func1func2 的返回类型与process_results 的参数不匹配。您缺少显示它们如何获取参数的代码。
  • @Caleth 我更正了代码,func1func2 在 HTTP 请求完成并解析文本响应时被调用。当订单和交易都被解析时,我需要调用process_result

标签: c++ c++20


【解决方案1】:

您需要某种同步点。到目前为止还没有使用 co_await,所以这可能不是你想要的,但是在 c++17 中我会选择 std::promise / std::future,可能是这样的:

#include <iostream>
#include <functional>
#include <future>

std::promise<std::string> p1;
std::function<void (std::string)> func1 = [](std::string http_answer)
{
    // std::vector<model::Order> orders = ParseOrders(http_answer);
    // std::cout << "Fetched " << orders.size() << " open/closed orders.");
    p1.set_value(http_answer);
};

std::promise<std::string> p2;
std::function<void (std::string)> func2 = [](std::string http_answer)
{
    // std::vector<model::Trade> trades = ParseTrades(http_answer);
    // std::cout << "Fetched " << trades.size() << " trades.");
    p2.set_value(http_answer);
};

int main () {

    // whenever that happens...
    func1("foo");
    func2("bar");

    // synchronize on func1 and func2 finished
    auto answer1 = p1.get_future().get();
    auto answer2 = p2.get_future().get();

    auto process_result = [&](/* std::vector<model::Order> orders,  std::vector<model::Trades> trades */)
    {
        std::cout << "Matching orders and trades... " << answer1 << answer2;
    };

    process_result();

    return 0;
}

http://coliru.stacked-crooked.com/a/3c74f00125999fb6

https://en.cppreference.com/w/cpp/thread/future

【讨论】:

  • p1.get_future().get(); 会阻塞线程吗?在我的应用中它不应该。
  • 是的,它会阻塞调用线程。但是,std::future 具有waitwait_for,您可以在其中轮询结果状态(类似于轮询/选择)。 en.cppreference.com/w/cpp/thread/future/waiten.cppreference.com/w/cpp/thread/future/wait_for
  • 我认为p1.get_future().get(); 被假定在一个单独的线程上被调用。如果我只是删除 get_future() 调用,您的代码会发生什么变化?并使用简单的变量而不是promise?
  • 这是常见的用例,是的。如果您的应用程序保证是单线程的,您可以将结果与特定条件一起存储在一个简单的变量中,以检查结果是否准备就绪。在我上面的代码中,您当然可以只检查结果字符串是否为!empty() 但是,由于您要求类似co_await 的内容,我认为肯定有一些多线程线程到位。
  • 我没有找到更好的解决方案,即使用一些在设置参数时调用函数的聚合器,请参阅github.com/dmitriano/Awl/blob/master/Tests/AggregatorTest.cpp
猜你喜欢
  • 1970-01-01
  • 2019-04-26
  • 2012-02-25
  • 2013-10-23
  • 2012-04-03
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
相关资源
最近更新 更多