簡體   English   中英

如何檢查io_service中的任務是否完成?

[英]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));
    }
}

幾點評論:

  1. 在構造函數中創建線程池

  2. 在析構函數中的工作將被刪除,因此io_service::run僅在沒有待處理的任務時返回

  3. 析構函數的功能可以包裝到成員函數中-例如wait ,那么您不必使用{}作用域來等待任務。

io_service::run文檔

run()函數將阻塞,直到所有工作都完成並且不再需要調度處理程序為止,或者直到io_context被停止為止。

另外,從io_context::work構造函數文檔中

構造函數用於通知io_context一些工作已經開始。 這樣可以確保io_context對象的run()函數不會在工作進行時退出

[強調我的]

簡而言之,如果run函數返回,而stopped函數返回false,則說明所有工作已經完成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM