[SOLVED] How to wait in a proper way for multiple signals?
-
Hi,
I would like to wait for multiple signals.
One class loads data to be processed. Then the data is processed in several class instances in different threads.
After all threads are finished I would like to load new data for processing.In the data loading class I have a corresponding function to set bool variables whether a thread is active or not.
The threadStarted signal is used to set the bool variables to active and the threadFinished signal is used to set them to non active.I just use a while loop where I am waiting that all bool variables are zero for inactive.
In the console I checked the order of starting and stopping and all variables are set in a proper order.
Sadly the program does not leave the while loop sometimes and just hangs.Do you have an idea what could be wrong or how to wait in a better way?
EDIT: I just noticed it just happens if the while loop is empty.
If I wait for 1 ms after every check, it does not hang anymore, but why is that?Thank you very much :-)
-
Can you post your while loop code?
When you introduce a 1ms wait, you are also providing a cancellation/switching point. Meaning that your process can have a chance to go off and do other things. Without that wait your loop is probably taking 100% of processing time.
A better way to do this is without a loop per say. You can run in a more state-machine/event driven way, such that when you receive a "Thread complete" signal, you check the state of all the threads. If they are not all finished then do nothing. If they are all finished, then do your "finish action" (this could be to emit a signal or anything). Would be easier to describe better what to do if we can see your loop code : )
-
Ok, thank you very much :-)
This is my code:
.cpp:while(processingThread1active==true || processingThread2active==true || processingThread3active==true || processingThread4active==true || processingThread5active==true || processingThread6active==true ) { waitKey(1); //there must be something done in the while loop otherwise it hangs! }
.h:
private slots: void thread1Started() {processingThread1active=true; std::cout << "1start" << std::endl;} void thread2Started() {processingThread2active=true; std::cout << "2start" << std::endl;} void thread3Started() {processingThread3active=true; std::cout << "3start" << std::endl;} void thread4Started() {processingThread4active=true; std::cout << "4start" << std::endl;} void thread5Started() {processingThread5active=true; std::cout << "5start" << std::endl;} void thread6Started() {processingThread6active=true; std::cout << "6start" << std::endl;} void thread1Finished() {processingThread1active=false; std::cout << "1stopp" << std::endl;} void thread2Finished() {processingThread2active=false; std::cout << "2stopp" << std::endl;} void thread3Finished() {processingThread3active=false; std::cout << "3stopp" << std::endl;} void thread4Finished() {processingThread4active=false; std::cout << "4stopp" << std::endl;} void thread5Finished() {processingThread5active=false; std::cout << "5stopp" << std::endl;} void thread6Finished() {processingThread6active=false; std::cout << "6stopp" << std::endl;}
-
Ok, thank you very much :-)
This is my code:
.cpp:while(processingThread1active==true || processingThread2active==true || processingThread3active==true || processingThread4active==true || processingThread5active==true || processingThread6active==true ) { waitKey(1); //there must be something done in the while loop otherwise it hangs! }
.h:
private slots: void thread1Started() {processingThread1active=true; std::cout << "1start" << std::endl;} void thread2Started() {processingThread2active=true; std::cout << "2start" << std::endl;} void thread3Started() {processingThread3active=true; std::cout << "3start" << std::endl;} void thread4Started() {processingThread4active=true; std::cout << "4start" << std::endl;} void thread5Started() {processingThread5active=true; std::cout << "5start" << std::endl;} void thread6Started() {processingThread6active=true; std::cout << "6start" << std::endl;} void thread1Finished() {processingThread1active=false; std::cout << "1stopp" << std::endl;} void thread2Finished() {processingThread2active=false; std::cout << "2stopp" << std::endl;} void thread3Finished() {processingThread3active=false; std::cout << "3stopp" << std::endl;} void thread4Finished() {processingThread4active=false; std::cout << "4stopp" << std::endl;} void thread5Finished() {processingThread5active=false; std::cout << "5stopp" << std::endl;} void thread6Finished() {processingThread6active=false; std::cout << "6stopp" << std::endl;}
@RolBri
So, yeah, I think what I said before is the case.Remove your while loop, and in your slot call a function:
void thread<x>Started() {handleThreadEvent(x, true)} void thread<x>Finished() {handleThreadEvent(x, false)} // <x> is the thread number
Then your function:
handleThreadEvent(int x, bool value) { // Make your flags an array of bools (easier to process) ProcessingThreadAactive[x] = value; // Check if threads are finished for (int i = 0; i < numThreads; i++) { bool finished = true; if (ProcessingThreadAactive[i] == true) { finished = false; // Do end actions here break; } } }
The advantage here is that you are only processing your check when your receive a thread event, also there is less repeated code) (not tested the code, so you may need to tweak it)
-
Thank you very much.
The problem is that the class is dependent on different timers and variables I have not mentioned.I understood your code and I see that this is far better than a loop, but because of the class structure it is a lot of work and not so easy to change it to a state machine.
If I can avoid the hanging I will stick to the loop solution.
Next time if I write something similar I take your solution :-)
-
Its true, if you can get your code to work for now then go with that, at least you understand what is happening and so it's your choice : )
Another option for you to mull over is conditional variables/mutex. I have not used the Qt version of this before but it works in the same way. Take a look at this. It allows you to keep your "wait" inline, but instead of polling values in a loop (inefficient), it allows the thread to "sleep/block" until notified. This would be easier to implement into an existing code base to replace a loop without modifying the structure of your code.
Requires a bit more work on your part, so if you can be bothered then its worth doing (even just to learn).
-
Could you please check your link?
It is not working :-(
I am really interested in the other solution as it looks like I cannot continue with my old way... ;-)@RolBri Oh... not sure what happened, let me try again:
Here is the link in text: http://doc.qt.io/qt-4.8/qwaitcondition.html
Let me try the auto format again: here