我最近一直在使用boost asio和一些新的C++ 11結構。以下是導致意外行爲的代碼示例部分(至少對我而言)。asio .async_ *將不會運行,除非主線程調用io_service.run
void Server::startAccept()
{
connections_.push_back(std::make_shared<Connection>(io_service_));
acceptor_.async_accept(connections_.back()->socket(), std::bind(&Server::accept_handler, this, connections_.back(), std::placeholders::_1));
}
void Server::accept_handler(std::shared_ptr<Connection> con, const boost::system::error_code& ec)
{
startAccept();
if (!ec) {
con->start();
}
}
我撥打電話到服務器:: startAccept之前,我創建io_service對象::工作的一個實例,)的std ::線程池,要求io_service_.run(。在我調用startAccept之後,主線程只是等待命令行輸入。
我希望我的線程池中的一個線程在連接啓動時運行Server :: accept_handler。這不會發生。相反,我必須從主線程調用io_service_.run()。
現在我玩了一段時間,我發現我可以通過這樣達到預期的行爲:
void Server::startAccept()
{
connections_.push_back(std::make_shared<Connection>(io_service_));
io_service_.post([this]() { acceptor_.async_accept(connections_.back()->socket(), std::bind(&Server::accept_handler, this, connections_.back(), std::placeholders::_1)); });
}
void Server::accept_handler(std::shared_ptr<Connection> con, const boost::system::error_code& ec)
{
startAccept();
if (!ec) {
con->start();
}
}
是什麼.async_之間的差異*操作和io_service.post?
編輯:定義BOOST_ASIO_ENABLE_HANDLER_TRACKING
當我編譯並運行了一個程序,然後連接到服務器的代碼,我包括第一塊是這樣的輸出:
@asio|1350656555.431359|0*1|[email protected]_accept
當我運行第二塊代碼我包括並連接到服務器我得到這個輸出:
@asio|1350656734.789896|0*1|[email protected]EC78.post
@asio|1350656734.789896|>1|
@asio|1350656734.789896|1*2|[email protected]_accept
@asio|1350656734.789896|<1|
@asio|1350656756.150051|>2|ec=system:0
@asio|1350656756.150051|2*3|[email protected]
@asio|1350656756.150051|>3|
@asio|1350656756.150051|2*4|[email protected]_send
@asio|1350656756.150051|3*5|[email protected]_accept
@asio|1350656756.150051|2*6|[email protected]_receive
@asio|1350656756.150051|<3|
@asio|1350656756.150051|>4|ec=system:0,bytes_transferred=54
@asio|1350656756.150051|<2|
@asio|1350656756.150051|<4|
@asio|1350656758.790803|>6|ec=system:10054,bytes_transferred=0
@asio|1350656758.790803|<6|
編輯2:創建線程的洞察力
for (int i = 0; i < NUM_WORKERS; i++) {
thread_pool.push_back(std::shared_ptr<std::thread>(new std::thread([this]() { io_service_.run(); })));
}
注意,它並沒有成爲_main_線程,它可以是任何線程。實際上它可能是_多個線程。 –
@ K-ballo我已經從另一個不是主線程的線程調用了io_service.run。只有在我提供的第一個代碼塊中的主線程調用io_service.run時,纔會執行Server :: accept_handler。 – flumpb
最初的代碼和描述看起來很好,並且這種行爲通常會來自[work](http://www.boost.org/doc/libs/1_51_0/doc/html/booster_asio/reference/io_service__work.html)對象超出範圍。但是,它沒有解釋後一種行爲。也許啓用[BOOST_ASIO_ENABLE_HANDLER_TRACKING](http://www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/overview/core/handler_tracking.html)將提供一些見解。 –