阅读 asio 的文档后,我很清楚完成处理程序是由调用io_serviceio.run()
方法的线程之一调用的。但是,我不清楚的是读/写异步方法发生在哪个线程。是我调用方法的线程,还是在调用io.run()
方法的线程之一中?或者,在最后一种情况下,库是否在后台创建另一个线程并执行操作?
将在启动async_*
函数中尝试 I/O 操作。 如果满足操作的完成条件或发生错误,则操作已完成,完成处理程序将发布到io_service
中。 否则,该操作不完整,它将被排队进入io_service
,运行io_service
函数的应用程序线程poll()
、poll_one()
、run()
或run_one()
执行底层的I/O操作。 在这两种情况下,完成处理程序都由处理io_service
的线程调用。
async_write()
文档指出异步操作可以立即完成:
无论异步操作是否立即完成,都不会从此函数中调用处理程序。处理程序的调用将以等效于 使用
boost::asio::io_service::post()
的方式执行。
异步操作要求文档中也指出了此行为:
异步操作完成后,将通过以下方式调用该操作的处理程序:
- 为处理程序构造绑定完成处理程序
bch
...- 调用
ios.post(bch)
以安排处理程序进行延迟调用...这意味着不得直接从启动函数中调用处理程序,即使异步操作立即完成也是如此。
下面是演示此行为的完整示例。 在其中,socket1
和socket2
是相连的。 最初,socket2
没有可用的数据。 但是,在调用async_write(socket1, ...)
后,即使io_service
尚未运行,socket2
也有数据:
#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());
}
例如,您希望将一些数据发送到远程合作伙伴 - 异步。
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_
已经建议的那样。