boost::asio::thread_pool - 如何在工作完成前取消工人?

Posted

技术标签:

【中文标题】boost::asio::thread_pool - 如何在工作完成前取消工人?【英文标题】:boost::asio::thread_pool - How to cancel workers before work is finished? 【发布时间】:2021-12-22 01:47:04 【问题描述】:

操作系统窗口。我想在绘制之前创建一个后缓冲区。我想使用 boost::asio::thread_pool 来提高速度。如果我的“输入数据”(任务)被更新,我需要停止创建后台缓冲区。 我写了 Test_CreateAndCancel 函数来简化测试。

class Task

public:
    virtual void operator()
    
        std::cout << "Task started " << std::endl;
        DoSomeWork();
        std::cout << "Task in progress" << std::endl;

        for (int i = 0; i < 15; ++i)
             boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));

        std::cout << "Task ended" << std::endl;
    
;
using TaskPtr = std::shared_ptr<Task>;


void Test_CreateAndCancel(std::vector<TaskPtr> &tasks)

    //start back-buffer creating
    boost::asio::thread_pool _thread_pool(4);
    for (auto task : tasks)
    
         boost::asio::post(thread_pool, [task] 
             task->operator()();
        );
    

    //  simulate cancel 
    thread_pool.stop(); // wait untill all threads are finished?

向量任务有 4 个项目。 结果是:4“任务开始”“任务进行中”“任务结束”

我正在考虑在 task::operator() 中添加自定义 IsCanceled() 检查。

还有其他方法可以取消我的任务吗? 如何实现取消逻辑?

如有任何建议,我将不胜感激 谢谢

【问题讨论】:

比较boost.org/doc/libs/1_77_0/doc/html/thread/…,或Concurrency In Action 的第9 章(Manning 在线免费) 【参考方案1】:

最简单的方法是在您的任务中添加一个(可能是原子的)变量“please_stop”,然后

定期在 operator() 内查询 从外部设置(另一个任务)

基本问题是您无法取消在不同任务中运行的操作。您只能“礼貌地请求”停止工作。


boost::thread 有一个中断机制(参见上面发布的链接,@sehe)。这基本上与我的建议没有什么不同,除了它被嵌入到 boost::thread 中。有某些“中断点”会查询“请停止”状态并抛出异常(如果已设置)。

您必须捕获异常,否则线程本身将停止,您只想停止操作。

所以你可以这样做:

class Task 
   virtual void operator()()
   
      try 
         do_something();
         boost::this_thread::sleep(boost::chrono::seconds(10000);
      
      catch (boost::thread_interrupted&)  // 
         handle_please_stop_request();
      
   
;

// and later
   task_thread.interrupt();

这种方法的问题是你必须知道线程并且你可能想要中断的不是线程而是操作。这就是原子方法有其魅力的原因。

顺便说一句,你的例子有几个问题。任务操作 (operator()()) 永远不会停止。您正在为每个任务向量创建一个任务池。我假设这些只是您的示例的工件,您的真实世界代码是不同的。

但有一件事。我还没有研究 asio::thread_pool,但我错过了 boost::asio::work 对象。在 *** 中搜索如何使用工作对象。

【讨论】:

以上是关于boost::asio::thread_pool - 如何在工作完成前取消工人?的主要内容,如果未能解决你的问题,请参考以下文章

Helgrind 在简单的 boost::asio::thread_pool 程序中报告同步错误

等到发布到 boost::asio::thread_pool 的作业(与所有作业完全相反)完成?