QThread将结果数据传递给MainThread

时间:2017-03-31 22:42:31

标签: c++ multithreading qt qthread

我正在考虑如何将结果数据从某个工作线程传递回客户端而不进行复制。 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;
}

看起来不错吗?或者有更合适的方法来做到这一点?

1 个答案:

答案 0 :(得分:2)

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

  

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

仅仅为了内存管理而进入QObject是一种过度杀伤QObject提供了much more stuff(内省功能,动态属性,信号/插槽,线程关联,事件处理,国际化...),这里您并不需要。

如果您只对内存管理感兴趣,Qtthe C++ standard library都有智能指针,可以通过唯一所有权或共享所有权语义实现对象生存期管理。

请查看this answer以获取将数据加载到全局线程池的模型示例,并在它们准备就绪后立即在视图中显示这些数据。请注意,模型继承QObject(因为QAbstractItemModel继承QObject,因为它使用信号/槽来通知视图数据更改)但是没有理由认为数据结构实际上存在要继承QObject的数据。 。