这些方法并非明确互斥。我经常看到第一种和第二种的组合:
- 一个或多个线程在一个
io_service
中处理网络I/O。
- 长时间运行的或阻塞的任务被发布到另一个
io_service
中。 这个io_service
作为线程池,不会干扰处理网络I/O的线程。或者,每次需要长时间运行或阻塞的任务时可以生成一个分离的线程; 然而,线程创建/销毁的开销可能会有显著的影响。
这是一个提供线程池实现的答案。此外,这里有一个基本示例,试图强调两个io_services
之间的交互。
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/chrono.hpp>
#include <boost/optional.hpp>
#include <boost/thread.hpp>
boost::asio::io_service background_service;
boost::asio::io_service io_service;
boost::optional<boost::asio::io_service::work> work;
template <typename Handler>
void query_odbc(unsigned int data,
Handler handler)
{
std::cout << "in background service, start querying odbc\n";
std::cout.flush();
boost::this_thread::sleep_for(boost::chrono::seconds(5));
std::cout << "in background service, posting odbc result to main service\n";
std::cout.flush();
io_service.post(boost::bind(handler, data * 2));
}
void handle_read_odbc(unsigned int result)
{
std::stringstream stream;
stream << "in main service, got " << result << " from odbc.\n";
std::cout << stream.str();
std::cout.flush();
work = boost::none;
}
void handle_read(const boost::system::error_code& error,
std::size_t bytes_transferred)
{
std::cout << "in main service, need to query odbc" << std::endl;
typedef void (*handler_type)(unsigned int);
background_service.post(boost::bind(&query_odbc<handler_type>,
21,
&handle_read_odbc)
);
work = boost::in_place(boost::ref(io_service));
}
void print_loop(unsigned int iteration)
{
if (!iteration) return;
std::cout << " in main service, doing work.\n";
std::cout.flush();
boost::this_thread::sleep_for(boost::chrono::seconds(1));
io_service.post(boost::bind(&print_loop, --iteration));
}
int main()
{
boost::optional<boost::asio::io_service::work> background_work(
boost::in_place(boost::ref(background_service)));
boost::thread_group background_threads;
for (std::size_t i = 0; i < 3; ++i)
background_threads.create_thread(
boost::bind(&boost::asio::io_service::run, &background_service));
io_service.post(boost::bind(&handle_read,
make_error_code(boost::system::errc::success), 0));
io_service.post(boost::bind(&print_loop, 5));
io_service.run();
background_work = boost::none;
background_threads.join_all();
}
输出结果:
在主服务中,需要查询ODBC。
在主服务中,正在工作。
在后台服务中,开始查询ODBC。
在主服务中,正在工作。
在主服务中,正在工作。
在主服务中,正在工作。
在主服务中,正在工作。
在后台服务中,将ODBC结果发布到主服务中。
在主服务中,从ODBC获得了42。
请注意,处理主io_service
的单个线程将任务发布到background_service
,然后继续处理其事件循环,而background_service
则会阻塞。一旦background_service
获得结果,它将把处理程序发布到主io_service
中。