【问题标题】:Which thread async operations take place发生哪些线程异步操作
【发布时间】:2017-11-13 20:42:53
【问题描述】:

阅读 asio 的文档后,我很清楚完成处理程序是由调用 io_service 的 io.run() 方法的线程之一调用的。但是,我不清楚的是读/写异步方法发生在哪个线程。是我调用方法的线程还是调用io.run() 方法的线程之一?或者,在最后一种情况下,库是否在幕后创建另一个线程并执行操作?

【问题讨论】:

  • 这是因为你想知道它是否阻塞了一些操作,还是因为你想知道线程局部变量处于什么状态,或者其他什么目的?
  • 这是因为我正在开发一个关键应用程序,我不能浪费时间在我的应用程序正在运行的线程上编写代码。我知道我可以发布一个 lambda 来执行我的 io_service,以便在调用 run() 方法的线程之一上进行写入操作。但是,如果库本身创建一个线程另一个线程来执行写操作,则没有必要发布到 io_service。
  • Platform-Specific Implementation Notes 文档记录了所有内部线程的创建和用途。没有一个内部线程将服务于写操作。

标签: c++ multithreading boost boost-asio


【解决方案1】:

I/O 操作将在初始化 async_* 函数中尝试。如果满足操作的完成条件或发生错误,则操作完成并且完成处理程序将发送到io_service。否则,操作未完成,将被排入io_service,其中运行io_service的函数poll()poll_one()run()run_one()的应用程序线程执行底层输入输出操作。在这两种情况下,完成处理程序都由处理io_service 的线程调用。

async_write() 文档说明异步操作可以立即完成:

无论异步操作是否立即完成,都不会在此函数中调用处理程序。处理程序的调用将以等同于使用boost::asio::io_service::post() 的方式执行。

Requirements on Asynchronous Operations 文档中也提到了这种行为:

当一个异步操作完成时,该操作的处理程序将被调用,好像是:

  • 为处理程序构造绑定完成处理程序bch ...
  • 调用ios.post(bch) 来安排延迟调用的处理程序...

这意味着不能直接从启动函数中调用处理程序,即使异步操作立即完成。


这是一个完整的例子demonstrating这个行为。其中,socket1socket2 是连接的。最初,socket2 没有可用数据。但是,在调用async_write(socket1, ...) 之后,socket2 有数据,即使 io_service 还没有运行:

#include <boost/asio.hpp>

constexpr auto noop = [](auto&& ...){};

int main()
{
  using boost::asio::ip::tcp;
  boost::asio::io_service io_service;

  // Create all I/O objects.
  tcp::acceptor acceptor{io_service, {{}, 0}};
  tcp::socket socket1{io_service};
  tcp::socket socket2{io_service};

  // Connect sockets.
  acceptor.async_accept(socket1, noop);
  socket2.async_connect(acceptor.local_endpoint(), noop);
  io_service.run();
  io_service.reset();

  // Verify socket2 has no data.
  assert(0 == socket2.available());

  // Initiate an asynchronous write.  However, do not run
  // the `io_service`.
  std::string data{"example"};
  async_write(socket1, boost::asio::buffer(data), noop);

  // Verify socket2 has data.
  assert(0 < socket2.available());
}

【讨论】:

    【解决方案2】:

    例如,您想向远程合作伙伴发送一些数据 - 异步。

    boost::asio::async_write(_socket, boost::asio::buffer(msg.data(), msg.size()),
        std::bind(&Socket::WriteHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2));
    //Where 'this' is the class Socket
    

    在此之前,您可能已经创建了一个名为ioService.run() 的线程。 async_write 函数将采用与您创建套接字时相同的 ioService。它将它放入您的 ioService 的队列中以执行写入操作和处理程序 - 在您的 ioService 运行的线程上,正如 async_ 已经建议的那样。

    【讨论】:

    • 这就是我所怀疑的。但是,由于我没有在 boost 文档中明确看到这一点,因此我不想做出任何假设。
    猜你喜欢
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 2023-03-16
    • 2016-06-08
    • 1970-01-01
    相关资源
    最近更新 更多