Multithreading – passing qlist * to signals from qthread
In my QT application, I have a class called from an object running in a thread In my worker class, I created qlist, just like this
QList <QString> albums; while (i.hasNext()) { QRegularExpressionMatch album = i.next(); albums.append(album.captured("album")); } emit SignalGotAlbums(albums);
I received this signal in another class containing my worker for thread use We call this class getalbumsthread There I successfully received signalgotalbums in a slot
void GetAlbumsThread::Reply(QList <QString> &list) { emit gotAlbums(list); emit finished(); }
In this slot, I send another signal gotalbums, assuming it is connected to a slot in my GUI thread and passes my qlist there My problem is that when I try to pass qlist from a thread to the GUI, it just doesn't work! The slot does not receive the gotalbums signal;
The signal statement is as follows:
void gotAlbums(QList<QString> &);
And connect to my GUI slot (in my GUI thread of course):
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 has never been called for some reason Connect returns true Can someone help me with this I think the problem is passing qlist between threads
Solution
The problem here is that you are using the signal / slot reference, that is, qlist < qstring > & put This is not compatible with threads because they use their own private stack, in which case all you do is pass a pointer from one thread to another
The possibilities are:
>Using the original qlist < qstring > signal / slot will force replication. > Assign qlist < qstring > to use new (so it will enter the heap instead of the stack) and use qlist < qstring > * signal / slot
The following code illustrates both methods:
// 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>)),SLOT(bar(QList<int>))); QObject::connect(worker,SIGNAL(bar2(QList<int>*)),SLOT(bar2(QList<int>*))); QThread * thread = new QThread(); worker->moveToThread(thread); QObject::connect(thread,worker,SLOT(process())); QObject::connect(worker,SIGNAL(finished()),thread,SLOT(quit())); QObject::connect(thread,&app,SLOT(quit())); thread->start(); return app.exec(); }
Output:
1 2 3 4 5 6 7