c++ - Qt 在另一个线程中为工作对象排队退出事件

标签 c++ multithreading qt

MyClass 对象有一个 worker QObject,它在另一个线程中工作:

class MyClass {
....
private:
   QThread thread;
   Worker worker; // inherits QObject
};

...

worker.moveToThread(&thread);

现在,当我调用 thread.exit() 时,我的工作线程会立即停止。我希望它完成所有未决事件,然后退出。

我试过类似“排队退出”的方法:

connect(this, SIGNAL(signalFinish()),
        &thread, SLOT(quit()),Qt::QueuedConnection);

 ...

void MyClass::finish()
{
    emit signalFinish();
    worker.disconnect(); // do not queue any more events
    thread.wait();
}

但它不起作用。它将永远等待...

如何在事件循环将处理所有未决事件后停止 QThread

最佳答案

线程和 MyClass 实例都在同一个线程中 - 可能是主线程:

MyClass::MyClass() {
  ...
  Q_ASSERT(this->thread() == thread.thread());

然而,您排队到工作对象的事件转到工作线程:

  worker.moveToThread(&thread);
  Q_ASSERT(worker.thread() == &thread);
  Q_ASSERT(worker.thread() != thread.thread());

排队连接恰恰是错误的做法,因为一旦您在工作线程上等待,主线程的事件循环就不会运行,也不会向该线程发出更多事件。 quit 调用永远不会被传递,因为它是在主线程中传递的,但是主线程被阻塞了。

相反,利用 quit 作为线程安全方法的优势。从工作线程本身调用它:

//                                    vvvvvvv thread context object for the call
connect(this, &MyClass::signalFinish, &worker, [this]{ thread.quit(); });
// the `quit()` will execute in `worker.thread()`

请注意,线程上下文对象是调用将在其 thread() 中执行的对象。它应该不是 QThread例如,在大多数情况下!

signalFinish 发出时,携带上述仿函数的 QMetaCallEvent 将在工作线程的队列中排队,并将在任何现有调用(和其他)之后执行首先处理事件。

由于您在主线程中调用 finish,您可能不想在线程上等待,因为这会阻塞 GUI 并使您的应用程序无响应。

因为看起来您正在将作业项提交给工作线程,所以您可能会更好地使用 QtConcurrent::run 将作业项提交给线程池,并执行所有线程管理你。参见 this answer一个完整的例子。参见 this answerthat answer一些相关的花絮。

关于c++ - Qt 在另一个线程中为工作对象排队退出事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38223391/

相关文章:

python - 相当于Java的Python同步

c++ - 更改模型后 View 未更新

c++ - 在 c 中工作但在 c++ 中不工作的代码

java - 如何在线程结束时执行函数?

c++ - 可变函数 : expression contains unexpanded parameter pack 'args'

android - 如何在没有 runOnUiThread() 的情况下在服务中创建/运行 AsyncTask

c++ - Qt QGraphicsItem 中的 hoverLeaveEvent() 并不总是被调用

c++ - 这是使用 QPointer 的正确方法吗?

c++ - 如何将箭头::数组转换为标准:: vector ?

c++ - 奇数组中包含的数字