QThread 将结果数据传递给主线程

QThread pass result data to MainThread

本文关键字:线程 结果 数据 QThread      更新时间:2023-10-16

我正在考虑如何在不复制的情况下将结果数据从某个工作线程传递回客户端。Worker 存在于其他线程中,BigData 继承了 QObject。我的想法是改变数据的所有权:

class Worker: public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0): QObject(parent);
signals:
void resultReady(BigData *data);
public slots:
void doWork() {
BigData *data = new BigData(this); // alloc new Data
while (!dataReady) {
... // appending data 
}
// Data ready 
// clearing ownership
data->setParent(NULL); // data can't be moved to another thread with parent
data->moveToThread(NULL);
emit resultReady(data);
}
};
void MainWindow::handleResult(BigData *data)
{
if (currentData_) {
delete currentData_;
}
data->setParent(this); // set new ownership
// works only if data's thread is NULL
data->moveToThread(QApplication::instance()->thread()); 
currentData_ = data;
}

好看吗?还是有更合适的方法?

通常使用moveToThread()将对象从一个线程推送到另一个线程。这意味着,您可以编写data->moveToThread(QApplication::instance()->thread());以避免将线程关联设置为NULL然后从主线程更改它,而不是在doWork()插槽中执行data->moveToThread(NULL);。但是,将BigData实例移动到主线程后,请注意从工作线程触摸该QObject。另一件需要注意的事情是,在线程之间来回移动QObject可能会导致一些副作用,来自文档:

请注意,对象的所有活动计时器都将重置。计时器首先在当前线程中停止,然后在目标线程中重新启动(以相同的间隔)。因此,在线程之间不断移动对象可能会无限期地推迟计时器事件。

仅仅为了内存管理而QObject是矫枉过正的。QObject提供了更多你在这里并不真正需要的东西(内省功能、动态属性、信号/插槽、线程亲和力、事件处理、国际化......)。

如果您只对内存管理感兴趣,Qt和C++标准库具有智能指针,可以通过唯一所有权或共享所有权语义实现对象生命周期管理。

查看此答案,了解将数据加载卸载到全局线程池并在准备好后立即在视图中显示这些数据的模型示例。请注意,模型继承了QObject(因为QAbstractItemModel继承了QObject,因为它使用信号/槽来通知数据更改的视图),但实际保存数据的数据结构没有理由继承QObject