[Qt-interest] Is it safe to connect different threads by Qt::DirectConnection?
Mihail Naydenov
mlists at ymail.com
Sat Dec 5 17:26:12 CET 2009
>>
>>You should post some code, I (completely) fail to understand your configuration, and what the problem is.
>
>class workthread:QThread
>{
> public slot:
> void slot_fun()
> { some time-consuming code here;}
>}
>void workthread::run()
>{
> QTimer timer;
> QObject::connect(&timer,SIGNAL(timeout()),this,SLOT(slot_fun()));
> timer.start(...);
>}
>GUI thread(main thread)
>int main(int argc,char *argv[])
>{
> mythread = new workthread;
>}
>So now I want the slot function slot_fun() to run in the work thread ,not in the GUI thread.According to the documents,if the fifth parameter is not set,slot_fun() will run in the GUI thread which will cause the UI unresponsive.If the fifth parameter is set to be Qt::DirectConnection, slot_run() will run in work thread.This is what I need.But I want to know if it is thred-safe to do like this or if there is a better way I do not know.
It seams you misinterpreted the documentation.
"The fifth" by itself, cannot change where (in which thread) the the slot is executed.
Where it is executed depends on where the qobject "lives". In general qobjects live in the thread they are created in the first place until they are movedToThread.
Now in your example you have two qobjects: workthread and QTimer
You create workthread instance in main => mythread "lives" in the man (GUI) thread => all slots will be executed in the main thread.
You create QTime instance in QThread::run() - all objects, created in QThread::run() live in a different thread (understandably, considering this is "the code to be ran on a different thread").
Now, you indeed connect objects from diff. threads, but the other way around!
You send (thread safe) requests "from a different thread" to be handled in the gui thread! (slot in a object, living in the main thread)
Note, again however, no option in qobject::connect can possibly change the thread position of the objects. It is again the other way around - connect does not change the thread affinity of the objects - its changed based on it!
(this is, AutoConnection (the default) will be "modified" to be Direct if objects are on the same thread, and Queued if on diff.)
Anyway here is somewhat reversed (and working) example of your code that does do the heavy work in slot in a diff thread.
It is reversed because it creates the timer in the main thread and an work-doing-object on another.
#include <QtGui>
class worker : public QObject
{
Q_OBJECT
public slots:
void slot_fun()
{
//some time-consuming code here
for(int i=0; i < 1000; ++i)
{
if(i%100 == 0)
qDebug()<<"doing work..."<<i;
}
}
};
#include "main.moc"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTimer timer;
QThread workerthead;
workerthead.connect(&a,SIGNAL(aboutToQuit()), SLOT(quit()));
worker laborer;
laborer.moveToThread(&workerthead);
laborer.connect(&timer,SIGNAL(timeout()),SLOT(slot_fun()));
timer.start();
workerthead.start();
QWidget ui;
ui.show();
bool result = a.exec();
workerthead.wait();
return result;
}
Now, its not necessary for QTimer to be in the main, the important thing is - through the live of the app you can aways (safely) call the fun_slot()
from any object and from any thread and have work done in parallel !
AFAIK this is the only way to have work done in a slot on a diff thread.
(again)
At Qt team, please add at least one example about this technique!
MihailNaydenov
>>
>>>...
>>>
>>>Longchao.
>>>
>>
>>
>>
>
More information about the Qt-interest-old
mailing list