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
