4

在我的 qt 应用程序中,我有一个从线程中运行的对象调用的类(worker)。在我的工人阶级中,我创建了 QList,就像这样

QList <QString> albums;

while (i.hasNext())
{
  QRegularExpressionMatch album = i.next();
  albums.append(album.captured("album"));
}
emit SignalGotAlbums(albums);

我在另一个包装我的工人的类中收到这个信号,以供线程使用。我们将这个类称为 GetAlbumsThread。在那里我成功地在一个插槽中接收到 SignalGotAlbums

void GetAlbumsThread::Reply(QList <QString> &list)
{

 emit gotAlbums(list);
 emit finished();
}

在这个插槽中,我正在触发另一个信号 gotAlbums,该信号假定与我的 gui 线程中的一个插槽连接,并在那里传递我的 QList。我的问题是,当我试图将 QList 从线程传递到 gui 时,它只是不起作用!插槽未收到 gotAlbums 信号;

信号声明如下:

void gotAlbums(QList<QString> &);

并像这样连接到我的 gui 插槽(当然是在我的 gui 线程中):

private slots:
    void AlbumsReceived(QList<QString> &list)
    ...

    QThread* albumsThread = new QThread();

    GetAlbumsThread *albumsObject = new GetAlbumsThread();

    albumsObject->moveToThread(albumsThread);

    connect(albumsThread, SIGNAL(started()), albumsObject, SLOT(process()));

    connect(albumsObject, SIGNAL(gotAlbums(QList<QString> &)), this, SLOT(AlbumsReceived(QList<QString> &));

     albumsThread->start();

AlbumsReceived 出于某种原因永远不会被调用。连接返回真。有人可以帮我弄这个吗。我认为问题出在线程之间传递的 QList 中。

4

2 回答 2

5

这里的问题是您正在为您的信号/插槽使用参考,即QList<QString> &. 这与线程不兼容,因为它们使用自己的私有堆栈,在这种情况下,您所做的是将指向堆栈中对象的指针从一个线程传递到另一个线程。

可能性是:

  1. 使用原始QList<QString>信号/插槽,这将强制复制。
  2. QList<QString>用 a分配new(因此将进入堆而不是堆栈),并使用QList<QString> *信号/槽。

以下代码说明了这两种方法:

// A.h

#include <QObject>
#include <QDebug>

class A: public QObject
{
Q_OBJECT

public slots:
    void foo(int i) { qDebug() << i; }
    void bar(QList<int> l) { foreach(int i, l) qDebug() << i; }
    void bar2(QList<int> * l) { foreach(int i, *l) qDebug() << i; }
};


// Worker.h

#include <QObject>

class Worker: public QObject
{
    Q_OBJECT

public slots:
    void process()
{
        // pass an int
        emit foo(1);

        // pass a list by value
        emit bar(QList<int>() << 2 << 3 << 4);

        // pass a poniter to a list
        list = new QList<int>();
        *list << 5 << 6 << 7;
        emit bar2(list);

        emit finished();
    }

signals:
    void finished();
    void foo(int);
    void bar(QList<int>);   
    void bar2(QList<int> *); 

private:
    QList<int> * list;
};


// main.cpp

#include <QApplication>
#include <QThread>
#include <QObject>

#include "A.h"
#include "Worker.h"

int main(int argc, char** argv)
{
    QApplication app(argc, argv);

    A * a = new A();
    Worker * worker = new Worker();
    QObject::connect(worker, SIGNAL(foo(int)), a, SLOT(foo(int)));
    QObject::connect(worker, SIGNAL(bar(QList<int>)), a, SLOT(bar(QList<int>)));
    QObject::connect(worker, SIGNAL(bar2(QList<int>*)), a, SLOT(bar2(QList<int>*)));

    QThread * thread = new QThread();
    worker->moveToThread(thread);

    QObject::connect(thread, SIGNAL(started()), worker, SLOT(process()));
    QObject::connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    QObject::connect(thread, SIGNAL(finished()), &app, SLOT(quit()));
    thread->start();

    return app.exec();
}

输出:

1 
2 
3 
4 
5 
6 
7
于 2013-06-13T01:58:20.287 回答
4

您是否尝试在调用 Object::connect(...) 之前注册您的 QList 对象?

您可以使用以下代码声明元类型:

qRegisterMetaType< QList<QString> >( "QList<QString>" );
于 2013-06-12T22:52:57.930 回答