gpt4 book ai didi

multithreading - 如何使用QThreadPool取消线程

转载 作者:行者123 更新时间:2023-12-03 13:00:19 29 4
gpt4 key购买 nike

我不能共享代码,但是下面有一个例子。这是我的问题。想象一下,我有一个具有QThreadPool实例的 Controller 类。此类保留一个工作对象列表。启动可运行对象时,我将创建一个工作程序并将其提供给可运行对象。可运行对象在不同的​​线程上操作每个工作程序。当可运行项完成后,它将向 Controller 对象发出一个信号。然后, Controller 对象从工作程序中读取结果并删除工作程序。 Controller 保留所有工作程序的列表,以便可以在工作程序上设置cancel标志,以便线程可以在必要时提早退出。

问题是QThreadPool在销毁时将等待所有线程完成,这些线程将在 Controller 析构函数中。由于信号是从线程中触发时排队的,因此潜在地取消 Controller 析构函数中的工作程序将使信号排队以传递到 Controller 。但是由于 Controller 将位于析构函数的上下文中,因此这些信号不会到达 Controller 插槽,因此不会破坏工作对象。

也许我没有按照应有的方式处理线程池。如果我销毁了可运行对象中的worker对象,则有可能在另一个线程试图取消一个worker之前销毁该worker。任何人都可以推荐一种创建可取消线程池的好方法吗?

class Controller : public QObject {
Q_OBJECT
public:
virtual ~Controller();
QThreadPool pool;
void startTask();
Q_SLOT void onWorkerDone(Worker * worker);
QList<Worker*> workers;
void cancelAll();
}
void Controller::startTask() {
Worker * worker = new Worker();
connect(pool, SIGNAL(done(Worker *)), this, SLOT(onWorkerDone(Worker *));
workers << worker;
pool.start(new Runnable(worker);
}
void Controller::onWorkerDone(Worker * worker) {
if ( worker ) {
// read worker...
delete worker;
}
}
Controller::~Controller() {
cancelAll();
// Destructor now kills pool object.
// The pool will wait until all threads complete.
// If there are any workers still running on the
// other threads, their done() signals will be
// queued to this instance, and since we're in
// the dtor, they won't make it to the slot,
// and worker won't get deleted.
}
void Controller::cancelAll() {
// loop the list and call cancel.
}

最佳答案

简单的解决方案是将QThreadPool子类化,并向该类添加aboutToWait信号。该信号将需要在析构函数中发出。然后,您可以将信号连接到 Controller 的cancelAll()插槽。
为此,必须在工作人员列表之后声明该池!
假设您破坏了 Controller (this)。发生以下情况:

  • 会执行this.~Controller的正文。
    最后,该对象仍然是Controller的实例。现在必须将其分解为基类的实例。成员将按照相反的声明顺序销毁。
  • threadPool首先被销毁。 threadPool.~MyThreadPool发出aboutToWait
  • this.cancelAll运行,因为它是直接连接的。该调用源自moc生成的signal方法的实现。它让 worker 知道他们应该停下来。
  • 剩余threadPool.~MyThreadPool运行,并且成员(如果有的话)以相反的声明顺序销毁。 this现在是QThreadPool的实例。
  • threadPool.~QThreadPool运行并等待工作人员停止。随着每个工作程序停止,controller.onWorkerDone被调用,因为它直接连接到相关线程池的信号。最终,threadPool.~QObject运行的池被完全破坏了。
  • workers.~QList运行。
  • this.~QObject运行。
  • Controller 已完全销毁。
  • 关于multithreading - 如何使用QThreadPool取消线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22548957/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com