首页 > 解决方案 > `std::async` 用于 C++ 中的异步回复

问题描述

概述:我有一个客户端-服务器实现,它使用 DBus( sdbus-c++ ) 向服务器发送异步请求。现在我的服务器与同步运行的硬件 API 进行交互,并且需要大量时间来生成回复。所以我有一个std::queueat 服务器,它保存所有收到的异步请求,并一个一个地处理它们。处理完服务器后,以为发送的请求注册的回调的形式发回回复。

#client.h

class Client
{ 
    Client();
    ~Client();

    void sendRequestA() 
    {  
       ... use DBus async call to send request to server
    }

    void sendRequestB() {...}
    
    protected:
    virtual void replyCallbackA(const uint8_t& status) = 0 ; // ... callback invoked by the DBus server   
    virtual void replyCallbackB(const uint8_t& status) = 0 ;
}

Ì 面临使用std::async测试这个特定用例的问题。

#test.cpp


//std::future<void> gFuture;

class ClientTest : public Client
{
  ClientTest();
  ~ClientTest();
  
  std::future<void> m_future;

  virtual void replyCallbackA(const uint8_t& status) override
  {
      std::cout<<"replyCallbackA status = "<< status<< "\n";
      m_future.get();
      //gFuture.get();
  }

  virtual void replyCallbackB(const uint8_t& status) override
  {
      std::cout<<"replyCallbackB status = "<< status<< "\n";
      m_future.get();
      //gFuture.get();

  }

}

int main()
{
   ClientTest cTest;
   cTest.m_future = std::async(std::launch::async, &ClientTest::sendRequestA, &cTest);
   cTest.m_future = std::async(std::launch::async, &ClientTest::sendRequestB, &cTest);

   //gFuture = = std::async(std::launch::async, &ClientTest::sendRequestA, &cTest);  -- no change in behavior with use of a global std::future.
}

我在这里的理解是,将调用sendRequestA& sendRequestB,并且还将调用回调函数。
但是,在这种情况下,调用&main后立即退出,并且没有收到回调响应。sendRequestAsendRequestB

编辑:我也尝试过使用全局变量 for std::future,但行为是相同的。

谁能告诉我的理解有什么问题?

标签: c++asynchronousdbusstdasync

解决方案


std::async返回一个以传递给的函数的返回值完成的未来std::async

对未来的第二次分配将阻塞,直到调用sendRequestA完成(由于前一个std::future实例的析构函数而阻塞)。它不会等到收到回复回调(除非你被阻止,sendRequestA但这会很奇怪)。

m_future.get()在您的回复回调将阻塞,直到未来解决(sendRequestA返回)。但是,它已经发送(因为这是您获得回复的唯一方式),因此.get()呼叫将立即返回。

我认为您想使用更像std::promise. 在您的回复回调中,您将调用std::promise::set_value以解决未来问题。调用与std::promiseor关联的未来的析构函数std::future::get将阻塞直到std::promise::set_value被调用(或承诺被销毁)。


推荐阅读