我无法共享代码,但下面是一个例子。这是我的问题。想象一下,我有一个控制器类,它有一个QThreadPool实例。此类保留工作对象列表。当我启动一个runnable时,我创建一个worker并将它交给runnable。 runnable在不同的线程上操作每个worker。当runnable完成后,它会将信号发送回控制器对象。然后,控制器对象从worker中读取结果并删除worker。控制器保留所有工作程序的列表,以便它可以在工作程序上设置取消标志,以便线程可以在必要时提前退出。
问题是QThreadPool会在它被销毁时等待所有线程完成,这将在控制器析构函数中。由于信号在从线程触发时排队,因此可能取消控制器析构函数中的工作人员将对要传递给控制器的信号进行排队。但由于控制器将位于析构函数的上下文中,因此这些信号不会碰到控制器插槽,因此工作对象不会被破坏。
也许我没有以应有的方式处理线程池。如果我销毁runnable中的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.
}
答案 0 :(得分:1)
QThreadPool
。这是应用程序的对象,因此您应该使用QThreadPool::globalInstance()
Worker
课程中提供一些功能。你需要在Worker::run()
方法中使用一些循环,它将完成你的工作并汇集价值,这应该在循环完成时安全地改变。答案 1 :(得分:0)
简单的解决方案是子类QThreadPool
并向该类添加aboutToWait
信号。信号需要在析构函数中发出。然后,您可以将信号连接到控制器的cancelAll()
插槽。
要使其工作,必须在工人列表之后将声明为池
假设您销毁控制器(this
)。发生以下情况:
this.~Controller
的正文执行。
最后,该对象仍然是Controller
的实例。现在必须将其拆分为基类的实例。成员将按照声明的顺序进行破坏。
threadPool
。 threadPool.~MyThreadPool
发出aboutToWait
。
this.cancelAll
运行,因为它直接连接。该调用源于moc生成的信号方法的实现。它让工人知道他们应该停下来。
threadPool.~MyThreadPool
运行的余数,以及成员(如果有)以与声明相反的顺序被破坏。 this
现在是QThreadPool
。
threadPool.~QThreadPool
跑,等待工人停下来。当每个工作人员停止时,controller.onWorkerDone
被调用,因为它直接连接到相关的线程池信号。最终,threadPool.~QObject
运行池完全被破坏。
workers.~QList
运行。
this.~QObject
运行。
控制器完全被破坏。