PDA

View Full Version : Waiting for something



JonathanForQT4
2nd May 2007, 13:45
Hello all...

I have many instances of one class that is an implementation of QThread. I can only call a function in one of the class instances at a time (don't ask why..ehe) Was wondering how I wait for the finished signal of a thread before I call the next instance...

so ->

some loop
instance of qthread class
if(if there is previous thread && previous thread still running) then wait
after wait call method within QThread instance
end some loop

I'm guessing I should be using QWaitCondition or something?!?! read the qt documentation but can't put all the pieces together :(

thanks in any case,

Jonathan

JonathanForQT4
2nd May 2007, 14:28
out of curiosity, is there a function like sleep(ms) in QT?

marcel
2nd May 2007, 14:37
Only in QThread.
Outside of a QThread( like the GUI thread) you must use platform specific sleep funtions:
Mac: usleep( microsecs )
Win: Sleep( milisecs )

regards

JonathanForQT4
2nd May 2007, 14:53
glad to know I'm not going crazy...using the sleep function....but for some reason, when I emit the signal from the instance of QThread..it never reaches the class with the slot.....weird!

marcel
2nd May 2007, 14:59
Look at the debugger console. Does it say anything?
How do you create the thread?

Maybe the signal/slot connection is not queued ( as it should be )...

Regards

fullmetalcoder
2nd May 2007, 15:03
Only in QThread.
Outside of a QThread( like the GUI thread) you must use platform specific sleep funtions:
Mac: usleep( microsecs )
Win: Sleep( milisecs )

I may have missed something but the GUI thread should be accessible through QThread::currentThread() (if you're sure not to be in another thread...). If so it would be better to use platform independent functions of QThread to do this...

Alternatively, QThread::wait() can block the event loop until thread finish execution or you can build a loop checking QThread::isRunning() :


while ( thread->isRunning() )
{
//do some stub code here... possibly forced event processing...
}

Hope this helps... :)

marcel
2nd May 2007, 15:08
QThread::sleep is static protected.

Anyway, I stumbled on this one before and it's OK to use platform sleep functions. It works very well. Anyway, Qt also uses platform dependent functions underneath.

Regards

JonathanForQT4
2nd May 2007, 15:19
So here's my code now:

big loop going through instances of threads...

while(QThread::currentThread()->isRunning())
Sleep(1000);

create new instance of QThread

connect signals to slots

call method within instance.

end big loop


still hangs.... :(

basically the "call method within instance" is accessing something that only allows mutually exclusive access....

marcel
2nd May 2007, 15:30
You call a method from the GUI thread from a QThread instance?
Not so sure if this is good, because it may be an intensive operation ( is it? - depends on what you do in that function ).
Why don't you execute that function in the GUI thread as a response to a signal emitted from the QThread? This way the function will be executed in the main thread.

Now, the function is executed in the worker thread...And both get stuck until the function returns.

Do your slots get called now, when the signals are emitted from the worker threads?

Regards.

JonathanForQT4
2nd May 2007, 15:37
I call a method within the newly created instance of QThread from the main thread....I reread what I wrote and now understand why you think I'm calling a method within the main thread from a qthread :(

danadam
2nd May 2007, 15:40
big loop going through instances of threads...


while (QThread::currentThread()->isRunning())
Sleep(1000);
This condition will always return true. If it is the current thread it means that it is running.


create new instance of QThread
connect signals to slots
Be carefull here. You create QThread instances in this thread, so they live in this thread and their slots (in case of queued connection) are processed in this thread.


call method within instance.
If you just call a method then it will be executed in this thread. You should emit signal, but again, see what I have written above.


basically the "call method within instance" is accessing something that only allows mutually exclusive access....
I think QMutex should do the job.

marcel
2nd May 2007, 15:45
I also reread :) and I don't think this is OK:

while(QThread::currentThread()->isRunning())
Sleep(1000);

Current thread is always the GUI thread when the while starts. Why do you call a method from the worker thread? If it is a thread, then why can't it do it?

Could you explain what you're trying to achieve?

JonathanForQT4
2nd May 2007, 15:48
danadam thank you for this first tip!!!

I have also thought that I should use QMutex, but I don't have a clue of how to properly do this, should I be passing in an instance of QMutex to each thread and having a condition that when the mutex is free then the run() gets called?

Thanks for everyone's help!

JonathanForQT4
2nd May 2007, 15:54
ok, I'll try and explain everything again!

There is one main Gui thread. This main thread, has a vector of classes which are reimplemented QThreads....the vector is filled in a big loop. After the vector gets one of these classes, call them "ControlClass", this instance then gets a method call which starts the run() of the QThread. If the big loop continues without sleeping or waiting until the previous "ControlClass" has finished its run() then the next "ControlClass" will access something at the same time and the program crashes.

Hopefully this is a better explanation of what has happened :)

Cheers,

Jonathan

marcel
2nd May 2007, 15:55
You call QThread::run from the GUI thread? Well why didn't you say so? Because this is the problem.

Run is called automatically. All you have to do is issue a QThread::start for every thread that you create, and let it do it's job... It will notify you when it's finished.

QMutex is needed only to protect shared data ( or widgets ). You use a QMutex only if you know that two or more threads are susceptible of modifying some data at the same time...

Regards

JonathanForQT4
2nd May 2007, 16:01
I know that the thread will notify me when it's finished (using the finished() signal)....but how do I make this big loop wait on starting another thread before the last thread is finished.

As mentioned before each instance of "ControlClass" is trying to access something, which can only be accessed one at a time....so I think QMutex would be the right thing to use here, but I'm not sure how!

danadam
2nd May 2007, 16:46
I know that the thread will notify me when it's finished (using the finished() signal)....but how do I make this big loop wait on starting another thread before the last thread is finished.
You can call wait() method on your worker thread and the current thread will be block until worker finishes its work.

Another thing. Do you really need all those threads? Maybe just one thread would be enough? From what you have written it appears to me that they will be called sequentially anywway.

marcel
2nd May 2007, 17:25
I disagree.

You have to approach things differently and make another implementation.
You don't need a while loop.

Your QThreads will finish asynchronously, therefore you have to wait for the current worker thread finished() and in the slot connected to it start the next thread( that is, of course, if you need multiple threads), and connect its finished() signal this (the same) slot.

You continue with this until you have finished your additional, worker thread tasks.

There is no need to "kill" the GUI thread like that ( because that is what you do ). You can kill it with the close button :).

Anyway, if you would just let us in on your little secret, and just tell us what you want to achieve with all those threads, maybe we can come up with a better( with less threads ) solution.

Regards

JonathanForQT4
2nd May 2007, 17:27
danadam, you are correct, I do not need all these threads. I have since reprogrammed it so that when the finish signal is emitted, the connecting slot (in the gui main thread) then uses the same instance to call the method again with new parameters.

Thanks for making me think of this :D

JonathanForQT4
2nd May 2007, 17:30
marcel, there is/was no secret...the threads try and start a program and if two threads are doing it at the same time they create the same pipe ID and everything goes SNAFU. I did not write the pipe class...and am not editing it....so that's why I had to come up with another way of doing things.

edit://given you thanks since you reaffirmed my conclusion :D

marcel
2nd May 2007, 17:35
Understood...