![](/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.