In my qt application i have a class (worker) which is called from the object which runs in a thread. In my worker class i create QList, like this
QList <QString> albums;
while (i.hasNext())
{
QRegularExpressionMatch album = i.next();
albums.append(album.captured("album"));
}
emit SignalGotAlbums(albums);
I receive this signal in another class which is wrapping my worker, for thread-usage. Let's call this class GetAlbumsThread. In there i successfully receive SignalGotAlbums in a slot
void GetAlbumsThread::Reply(QList <QString> &list)
{
emit gotAlbums(list);
emit finished();
}
In this slot i'am firing another signal gotAlbums which is suppose to be connected with a slot in my gui thread, and pass my QList in there. My problem is, when im trying to pass QList from a thread to gui, it's just not working! Slot not receiving gotAlbums Signal;
Signal is declared like so:
void gotAlbums(QList<QString> &);
And connected to my gui slot (of course in my gui thread) like that:
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 never get's called for some reason. connect returns true. Can someone help me with this. I think the problem is in the passing QList between threads.
The issue here is that you are using a reference for your signal/slot, i.e. a QList<QString> &
. This is not compatible with threads since they use their own private stack, and in this case what you do is passing a pointer to an object in the stack from one thread to another.
Possibilities are:
QList<QString>
signals/slots, that will force a copy.QList<QString>
with a new
(hence will go in the heap instead of the stack), and use QList<QString> *
signals/slots.The following code illustrates these two 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>)), 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();
}
Output:
1
2
3
4
5
6
7
Did you try to register your QList object before calling Object::connect(...) ?
You can declare the meta-type using this code:
qRegisterMetaType< QList<QString> >( "QList<QString>" );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With