将QList <qstring> *传递给来自QThread </qstring>的信号

时间:2013-06-12 21:44:07

标签: multithreading qt signals qlist slot

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

QList <QString> albums;

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

我在另一个正在包装我的worker的类中收到此信号,以供线程使用。我们将此类称为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永远不会被调用。 connect返回true。有人可以帮我弄这个吗。我认为问题出在线程之间传递QList。

2 个答案:

答案 0 :(得分:4)

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

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

qRegisterMetaType< QList<QString> >( "QList<QString>" );

答案 1 :(得分:3)

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

可能性是:

  1. 使用原始QList<QString>信号/插槽,这将强制复制。
  2. 使用QList<QString>分配new(因此将进入堆而不是堆栈),并使用QList<QString> *信号/插槽。
  3. 以下代码说明了这两种方法:

    // 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