QThread with signals and slots
-
I've got the following code:
My class header:
@class MyClass : public QObject
{Q_OBJECT
public:
MyClass();
private slots:
void update(); //The slot
};@
My class cpp file:
@MyClass::MyClass()
{
MyThread *thread = new MyThread();
QObject::connect(thread, SIGNAL(signal()), this, SLOT(update()));
thread->start();
}void MyClass::update()
{
cout<< "Signal Called!!" << endl;
}@My thread class:
@class MyThread : public QThread
{Q_OBJECT
signals:
void signal();
public:
void run();
};@
My thread cpp file:
@void MyThread::run()
{
emit signal();
}@When I use the code above, the update slot is never accessed, that is "Signal called!!" is never printed.
BUT: when I change the following in MyClass's constructor:@thread->start();@
to:
@thread->run();@
then "Signal called!!" is printed.
Does anyone know why this is?
-
The main problem is, that goocreations is using QThread in the wrong way. QThread is a class managing a thread. It is not the thread itself.
This is a frequently returning topic, mostly because of documentation issues in this respect in Qt. The recommended way of working with threads in Qt has changed since the documentation was written. It is usually better not to add signals, let alone slots, to QThread. Instead, create a QObject (derived) instance, and call moveToThread on it to move it to the thread. Put your signals and slots in this worker object instead.
See "this blog":http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ for details.
-
I've tried doing this:
@QObject::connect(thread, SIGNAL(signal()), this, SLOT(update()), Qt::QueuedConnection);@
But the problem rremains
-
You make a connection between two objects that live in the same thread (your QThread instance lives in the thread that created it!). Then, you try to emit a signal from that object from another thread (inside run, you're in another thread). Doesn't sound like sane code to me...
-
Thanks Andre, I'm trying your way now:
I've created a (derived) instance of QObject (which includes a signal), connected the objects signal to my update slot (is that correct?)a nd I've used moveToThread. But how do I emit the signal from my thread, since MyThread doesn't have a signal at the moment?
-
It's a bit problematic if your objects are from diffrent threads
-
[quote author="goocreations" date="1294519650"]Thanks Andre, I'm trying your way now:
I've created a (derived) instance of QObject (which includes a signal), connected the objects signal to my update slot (is that correct?)a nd I've used moveToThread. But how do I emit the signal from my thread, since MyThread doesn't have a signal at the moment?[/quote]
http://developer.qt.nokia.com/wiki/ThreadsEventsQObjects :-)
-
Thanks peppe, I went through all that, and tried it, but without any success
-
No, no event loop is running in MyClass
-
[quote author="goocreations" date="1294519650"]Thanks Andre, I'm trying your way now:
I've created a (derived) instance of QObject (which includes a signal), connected the objects signal to my update slot (is that correct?)a nd I've used moveToThread. But how do I emit the signal from my thread, since MyThread doesn't have a signal at the moment?[/quote]
You start work in your thread by giving your worker object a slot. In the default implementation, your thread will get an event loop (run() calls exec()), so you can invoke a slot in it. You can invoke that slot by connecting a signal to it from the main thread, or by using QMetaObject::invokeMethod. In the latter case, don't forget to include the Qt::QueuedConnection flag, otherwise you make a direct method call and your slot won't be executed in the new threads' context, but in the main threads' context. -
[quote author="Andre" date="1294519136"]The main problem is, that goocreations is using QThread in the wrong way. QThread is a class managing a thread. It is not the thread itself.
This is a frequently returning topic, mostly because of documentation issues in this respect in Qt. The recommended way of working with threads in Qt has changed since the documentation was
[quote author="Andre" date="1294572814"][quote author="goocreations" date="1294519650"]Thanks Andre, I'm trying your way now:I've created a (derived) instance of QObject (which includes a signal), connected the objects signal to my update slot (is that correct?)a nd I've used moveToThread. But how do I emit the signal from my thread, since MyThread doesn't have a signal at the moment?[/quote]
You start work in your thread by giving your worker object a slot. In the default implementation, your thread will get an event loop (run() calls exec()), so you can invoke a slot in it. You can invoke that slot by connecting a signal to it from the main thread, or by using QMetaObject::invokeMethod. In the latter case, don't forget to include the Qt::QueuedConnection flag, otherwise you make a direct method call and your slot won't be executed in the new threads' context, but in the main threads' context.
[/quote]written. It is usually better not to add signals, let alone slots, to QThread. Instead, create a QObject (derived) instance, and call moveToThread on it to move it to the thread. Put your signals and slots in this worker object instead.
See "this blog":http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ for details.[/quote]
Hi , I was reading this old post , Then I was surprised after reading that documents are old and not correct way.
I read several post in Qt blog , with different Idea.... what is really the correct way ?
I am also confused now , what is the correct way of using movetothread !!!!by the way , I always use movetothread and I use signal and slots and I never had problem but I prefer to be on the correct way on implementation
thanks
-
Reference the blog and "this":http://developer.qt.nokia.com/wiki/ThreadsEventsQObjects wiki entry. Only based on the official Qt documentation, it is way too easy to get it wrong. Also, do not, please, use moveToThread(this) inside your QThread subclass. You probably don't understand what that does exactly, and what the consequences are.
-
Thank you very much. You are right. I am a bit confused now about movetothread while I know it is used later in the thread for events and ...
I need to get help by reading a source code which has correct implementation.
As I remember in the documents , ::Start() should not be called from the thread itself !!! while I see in the code "queuedcustomtype" (attached in the Qt Sources) the start has been called from a method inside the Thread Subclass !!!!! ? -
[quote]I need to get help by reading a source code which has correct implementation. As I remember in the documents , ::Start() should not be called from the thread itself ![/quote]
What do you mean with that? It's supposed to be called from the thread your thread object is living in. Calling a custom method foo() which in turns calls start() is perfectly fine.
-
Copy/paste from the mentioned wiki entry:
@
class Worker : public QObject
{
Q_OBJECTpublic slots:
void doWork() {
/* ... */
}
};/* ... */
QThread *thread = new QThread;
Worker *worker = new Worker;
connect(obj, SIGNAL(workReady()), worker, SLOT(doWork()));
worker->moveToThread(thread);
thread->start();
@