PDA

View Full Version : how to resume QThread::wait()?



naturalpsychic
26th January 2011, 16:24
Hi,
I am trying to run a class's void function called "show()", here is code:

in main.cpp



MyClassObj* cObj;
QThread thread;


for (int i=0 ; i<=vecObj.count() ; i++)
{
cObj=&vecObj[i][0];
cObj->moveToThread(&thread);


cObj->connect(&thread,SIGNAL(started()),SLOT(show()));
thread.connect(&thread,SIGNAL(finished()),&thread,SLOT(quit()));


thread.start();
thread.wait();


}

now issue is, this code runs fine for the first loop, but since thread.wait() is called at the end of loop, thread waits for execution to stop (waiting for thread.quit()) after first loop and i am not able "resume" this wait() condition so that show() is called again for next loop.

I am kinda stuck here, i have been going through many articles and forum discussion, haven't found any issue like this.

Any help will be greatfully appreciated.
Thanks in advance.

high_flyer
26th January 2011, 16:30
If you want your object to work sequentially, (you wait for each obj to finish before you start the next) then what do you need a thread for?
Lets say, its because the work done on each object is long, and you want the GUI responsive - ok.
On way is to get rid of the wait, and have a "thread starter" slot connected to the finished() signal of the threads, and then you can start the next.

But it looks to me you are trying to force using threads where they are not really needed, and that a proper design would simplify the whole thing dramatically.

naturalpsychic
26th January 2011, 16:51
thanks for reply


But it looks to me you are trying to force using threads where they are not really needed, and that a proper design would simplify the whole thing dramatically.

Yes you are right, i am trying to force using thread but it is needed at the same time, because of the same reason you mentioned, to keep my GUI responsive, without having threads my GUI will just go unresponsive.


On way is to get rid of the wait, and have a "thread starter" slot connected to the finished() signal of the threads, and then you can start the next.

i think you meant by:



cObj->connect(&thread,SIGNAL(started()),SLOT(show()));
thread.connect(&thread,SIGNAL(finished()),&thread,SLOT(start()));


thread.start();
//thread.wait(); //COMMENTED THIS OUT


but obviously it wont work either because none of thread is waiting to finish...and if i uncomment above thread.wait() then execution of thread never finishes to start next one, i mean finished() signal is never emitted from &thread obj.

high_flyer
26th January 2011, 17:57
There are all kinds of problems in what you are saying...
But I'll start from the end:
If you have some work that needs to be done out side the GUI thread, and that work has to be sequential, then why do you put all the stages in different threads?
Have one thread call the stages one aftter the other, instead of putting each stage in its own thread.
So something like:
1. Have your thread object take a list of the objects.
2. In run() iterate over the list and call the work functions on the objects.
3. In the gui thread just have your one worker thread notify you when it is finished.

naturalpsychic
26th January 2011, 18:48
Have one thread call the stages one aftter the other, instead of putting each stage in its own thread.

thanks so much
while i was waiting for a reply to my thread, this was exact same approach i tried, but i came across a problem,

now instead of having different threads in one loop, i have loop in one thread. Below is code for it followed by description of issue i am facing:



ItemList::ItemList()
{

cObj *_cobj;
_cobj=new cObj("arguments passed to constructor");
_cobj.properties="set properties and stuffs";

list.append(_cobj); //QVector object of 'cObj' type
_cobj=new cObj("diffr");
_cobj.properties="properties for this instance";

list.append(_cobj); //QVector object of 'cObj' type
createThread(); // to create thread...definition is below





void ListObj::createThread()
{
QThread *thread=new QThread;
cObj _cObj1=_cObjGLOBAL;

_cObj1->moveToThread(thread);



cObj1->connect(thread,SIGNAL(started()),SLOT(startProcess ())); //<<--------------------- This line
thread.connect(&thread,SIGNAL(finished()),&thread,SLOT(quit()));


thread.start();
thread.wait();
}

void ListObj::startProcess() //<<------------------------ REFERENCE1
{
for (i=0;i< list.count(); i++)
{
//process for each iteration
}
}



NOW problem is where above code lies "This line"... actually connect() looks for startProcess() in cObj, but i want reference to "REFERENCE1", i have tried following:



cObj1->connect(thread,SIGNAL(started()),this,SLOT(startPr ocess())); //<<----------with "this" as *receiver


but it gave me compile error:
no matching function for call to ‘_cObj::connect(QThread*&, const char*, ListObj* const, const char*)’


but it gave me compile error:
no matching function for call to ‘_cObj::connect(QThread*&, const char*, ListObj* const, const char*)’


Oh oki i have overcome this problem by looking at original signature of connect()...since my ListObj doesn't inherit QObject so it is not considered as QObject, what i did i inherited QObject and now everything is working all good...


Thanks alot guys

high_flyer
26th January 2011, 18:53
For this kind of execution you might want to have a look at QtConcurrent (http://doc.trolltech.com/4.7/qtconcurrent.html).

wysota
26th January 2011, 23:07
I suggest you read Keeping the GUI Responsive. And also read what QThread::wait() is for and why it doesn't work in your case. Also read about QWaitCondition. But focus on the first link I gave you, it's a comprehensive article describing different approaches you may take.