驻留在 QThread 中的 QObjects 自动删除了吗?
QObjects residing inside a QThread deleted automatically?
如果 QObject
被创建为 class 成员(例如 QWidget
)并且我们尝试将其移动到一个线程,它不起作用。
如果我们实例化一个 QObject
不是动态的,然后改变它的线程亲和力,它就不起作用。
所以需要做的是动态创建一个 QObject
,将其所有槽和信号连接到 UI(例如),然后将其移动到一个单独的线程。由于它是动态分配的,即使我们离开在本地生成它的函数(在函数范围内),它仍然存在于内存中。
我遇到的问题是了解 Qt 是否在我们退出后自动处理驻留在 QThread
中的 QObject
(QThread::quit()
然后等待线程完成在主偶数线程中完成合并)并删除 QThread
对象的实例。
我认为它没有,或者至少这是我在查看 valgrind
的输出时所看到的。所以我的问题是我们如何删除 QObject
其线程亲和性已更改且不再驻留在主线程中的线程?
我已经阅读了有关 QObject::deleteLater()
的文章,所以我相信这是可行的方法。但是我不知道什么时候应用它。
考虑以下代码:
void MyWidget::setup()
{
thread = new QThread();
OpenCvWorker *worker = new OpenCvWorker();
QTimer *workerTrigger = new QTimer();
workerTrigger->setInterval(1);
connect(workerTrigger, SIGNAL(timeout()), worker, SLOT(receiveGrabFrame()));
connect(this, SIGNAL(sendSetup(int)), worker, SLOT(receiveSetup(int)));
connect(this, SIGNAL(sendToggleStream()), worker, SLOT(receiveToggleStream()));
connect(ui->pushButtonPlay, SIGNAL(clicked(bool)), this, SLOT(receiveToggleStream()));
connect(ui->checkBoxEnableBinaryThreshold, SIGNAL(toggled(bool)), worker, SLOT(receiveEnableBinaryThreshold()));
connect(ui->spinBoxBinaryThreshold, SIGNAL(valueChanged(int)), worker, SLOT(receiveBinaryThreshold(int)));
connect(worker, SIGNAL(sendFrame(QImage)), this, SLOT(receiveFrame(QImage)));
workerTrigger->start();
worker->moveToThread(thread);
// worker->deleteLater();
workerTrigger->moveToThread(thread);
// workerTrigger->deleteLater();
thread->start();
emit sendSetup(0);
}
这里我创建了一个worker实例(继承自QObject
)和一个QTimer
实例。然后我将我的 UI 连接到 worker 以及用于每毫秒触发一些甚至在 worker 内部的计时器。之后,我将工作人员和计时器都移动到创建的 QThread
实例和 运行 我的单独线程。
如您所见,两者都是动态分配的。但是由于范围界定(不能以任何其他方式做到这一点,因为 QObject
在移动到单独的线程时不应该有父级并将其创建为 class 成员基本上就是这样)我想不出释放分配内存的方法。
任何人都可以分享 his/her 经验吗?我真的不知道下一步该怎么做,我在互联网上搜索(包括 SO)时找不到任何有用的东西。
您可以将它连接到 QThread::finished
信号,另请参阅 http://doc.qt.io/qt-5/qthread.html#signals. Please read the Qt documentation, it is actually quite good. http://doc.qt.io/qt-5/qthread.html#details 包含您需要的所有信息。
如果 QObject
被创建为 class 成员(例如 QWidget
)并且我们尝试将其移动到一个线程,它不起作用。
如果我们实例化一个 QObject
不是动态的,然后改变它的线程亲和力,它就不起作用。
所以需要做的是动态创建一个 QObject
,将其所有槽和信号连接到 UI(例如),然后将其移动到一个单独的线程。由于它是动态分配的,即使我们离开在本地生成它的函数(在函数范围内),它仍然存在于内存中。
我遇到的问题是了解 Qt 是否在我们退出后自动处理驻留在 QThread
中的 QObject
(QThread::quit()
然后等待线程完成在主偶数线程中完成合并)并删除 QThread
对象的实例。
我认为它没有,或者至少这是我在查看 valgrind
的输出时所看到的。所以我的问题是我们如何删除 QObject
其线程亲和性已更改且不再驻留在主线程中的线程?
我已经阅读了有关 QObject::deleteLater()
的文章,所以我相信这是可行的方法。但是我不知道什么时候应用它。
考虑以下代码:
void MyWidget::setup()
{
thread = new QThread();
OpenCvWorker *worker = new OpenCvWorker();
QTimer *workerTrigger = new QTimer();
workerTrigger->setInterval(1);
connect(workerTrigger, SIGNAL(timeout()), worker, SLOT(receiveGrabFrame()));
connect(this, SIGNAL(sendSetup(int)), worker, SLOT(receiveSetup(int)));
connect(this, SIGNAL(sendToggleStream()), worker, SLOT(receiveToggleStream()));
connect(ui->pushButtonPlay, SIGNAL(clicked(bool)), this, SLOT(receiveToggleStream()));
connect(ui->checkBoxEnableBinaryThreshold, SIGNAL(toggled(bool)), worker, SLOT(receiveEnableBinaryThreshold()));
connect(ui->spinBoxBinaryThreshold, SIGNAL(valueChanged(int)), worker, SLOT(receiveBinaryThreshold(int)));
connect(worker, SIGNAL(sendFrame(QImage)), this, SLOT(receiveFrame(QImage)));
workerTrigger->start();
worker->moveToThread(thread);
// worker->deleteLater();
workerTrigger->moveToThread(thread);
// workerTrigger->deleteLater();
thread->start();
emit sendSetup(0);
}
这里我创建了一个worker实例(继承自QObject
)和一个QTimer
实例。然后我将我的 UI 连接到 worker 以及用于每毫秒触发一些甚至在 worker 内部的计时器。之后,我将工作人员和计时器都移动到创建的 QThread
实例和 运行 我的单独线程。
如您所见,两者都是动态分配的。但是由于范围界定(不能以任何其他方式做到这一点,因为 QObject
在移动到单独的线程时不应该有父级并将其创建为 class 成员基本上就是这样)我想不出释放分配内存的方法。
任何人都可以分享 his/her 经验吗?我真的不知道下一步该怎么做,我在互联网上搜索(包括 SO)时找不到任何有用的东西。
您可以将它连接到 QThread::finished
信号,另请参阅 http://doc.qt.io/qt-5/qthread.html#signals. Please read the Qt documentation, it is actually quite good. http://doc.qt.io/qt-5/qthread.html#details 包含您需要的所有信息。