![](/img/trans.png)
[英]How to check if boost::asio::io_service has started running?
[英]How to check whether tasks in io_service are completed?
我对boost::io_service
有疑问。
我有一组可以同时运行的任务。 运行完所有这些之后,我需要同时运行另一组任务。 但是,在开始运行第二组之前,必须先完成第一组。 这意味着在开始计划第二套作业之前,我需要确保提交给io_service的所有作业均已完成。
我可以通过保留某种计数器并添加一个繁忙的循环来实现它,但是它看起来不是很有效。 因此,我想检查某人是否有更好的主意。 以下是我用来进行实验的伪代码。
先感谢您!
#include <cstdio>
#include <iostream>
#include <unistd.h>
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
const size_t numTasks = 100000;
void print_counter(const size_t id)
{
if (id + 1 == numTasks) {
printf("sleeping for %ld\n", id);
sleep(15);
}
printf("%ld\n", id);
}
int main(int argc, char** argv)
{
using namespace std;
using namespace boost;
asio::io_service io_service;
asio::io_service::work work(io_service);
const size_t numWorker = 4;
boost::thread_group workers;
for(size_t i = 0; i < numWorker; ++i) {
workers.create_thread(boost::bind(&asio::io_service::run, &io_service));
}
for(size_t i = 0; i < numTasks; ++i) {
io_service.post(boost::bind(print_counter, i));
}
// TODO: wait until all the tasks are done above
for(size_t i = 0; i < numTasks; ++i) {
io_service.post(boost::bind(print_counter, i));
}
// TODO: wait until all the tasks are done above
// ...
// Finally stop the service
io_service.stop();
workers.join_all();
return 0;
}
您的主要问题是所有任务集都由io_service
的同一实例处理。 函数io_service::run
返回没有要处理的任务的地方。 io_service::work
析构函数通知io_service
对象, run
可以返回队列中没有待执行任务的地方。 您可以发布第一个任务集的所有任务,然后销毁工作并等待io_service::run
返回,然后再次创建work
对象,发布下一个任务集的任务并删除工作,依此类推。 为此,只需编写如下所示的帮助器类:
class TasksWaiter
{
public:
TasksWaiter(int numOfThreads)
{
work = std::make_unique<boost::asio::io_service::work>(io_service);
for(size_t i = 0; i < numOfThreads; ++i) {
workers.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
}
}
~TasksWaiter() {
work.reset();
workers.join_all();
}
template<class F>
void post(F f) {
io_service.post(f);
}
boost::thread_group workers;
boost::asio::io_service io_service;
std::unique_ptr<boost::asio::io_service::work> work;
};
int main()
{
{
TasksWaiter w1{4};
for (int i = 0; i < numTasks; ++i)
w1.post(boost::bind(print_counter,i));
// work in w1 is destroyed, then io_service::run ends
// when there are no tasks to be performed
}
printf("wait here");
{
TasksWaiter w1{4};
for (int i = 0; i < numTasks; ++i)
w1.post(boost::bind(print_counter,i));
}
}
几点评论:
在构造函数中创建线程池
在析构函数中的工作将被删除,因此io_service::run
仅在没有待处理的任务时返回
析构函数的功能可以包装到成员函数中-例如wait
,那么您不必使用{}
作用域来等待任务。
run()
函数将阻塞,直到所有工作都完成并且不再需要调度处理程序为止,或者直到io_context
被停止为止。
另外,从io_context::work
构造函数文档中 :
构造函数用于通知
io_context
一些工作已经开始。 这样可以确保io_context
对象的run()
函数不会在工作进行时退出 。
[强调我的]
简而言之,如果run
函数返回,而stopped
函数返回false,则说明所有工作已经完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.