Need multithreading advice
-
I have a function which can take a while to finish. It does some basic data mining and at the extreme it takes 20 seconds to complete. Currently this locks up the entire app and its UI until it is finished, and clearly I need to put this function on an independent thread. When the function completes, it sets a bool flag in my class so other functions know whether it is done; I check this bool during the frame cycle updates for the OpenGL drawing, so there is no need for me to use any features to directly query the function to see if it is finished.
I have read about QThread, thread pools, futures, and the QtConcurrent framework. I'm overwhelmed by the many options. If I just have this one function that needs to be multithreaded, can anyone recommend the simplest mechanism to do so?
-
Hi,
Since you only want to run 1 function in a separate thread, I recommend using QtConcurrent::run() -- http://qt-project.org/doc/qt-5/qtconcurrent.html#run
By the way, does the mined data get shared with the rest of your application? If so, make sure you pass the data between threads safely: http://qt-project.org/doc/qt-5/threads-synchronizing.html
-
Well, I'm trying to use the QtConcurrent::run() function and am following the example "here":http://qt-project.org/doc/qt-4.8/thread-basics.html#example-2-using-qtconcurrent however the compiler doesn't seem to like my call. I'm doing this:
QtConcurrent::run(&DataAnalysis::findGem);
findGem() is a function which takes no arguments. I also tried just using it without the &DataAnlaysis:: modifier. In either case the compiler says:
"term does not evaluate to a function taking zero arguments."
I also tried adding the () to the end of the findGem function. Something about this syntax is not working, does anything stand out to you?
-
A member function is different from a standalone function. If you want to use a member function, you'll also need to specify which instance of the class you're using: http://qt-project.org/doc/qt-5/qtconcurrentrun.html#using-member-functions
Also, if findGems() reads/writes the member variables of your DataAnalysis object, make sure you protect those variables with mutexes.
-
Actually looks like my issue is a known limitation of Qt's javascript engine:
-
[quote author="qttester5" date="1396418159"]Thanks, I got the run() to compile now, but this seems more complicated than I first suspected since the findGems() function also calls other member utility functions which I am guessing is not allowed from a different thread?[/quote]That depends on whether your member functions are thread-safe or not. If you make your functions thread-safe, then it's ok to call them from different threads.
[quote author="qttester5" date="1396418518"]Actually looks like my issue is a known limitation of Qt's javascript engine:
https://bugreports.qt-project.org/browse/QTBUG-33621[/quote]QObjects are not thread-safe.
It looks like you will need to redesign your code, so take this opportunity to create a solution based on signals-and-slots. Create a worker object whose purpose is to do your data mining in a secondary thread. Pass data between threads by emitting signals instead of reading variables directly.
See the first example in the "QThread documentation":http://qt-project.org/doc/qt-5/qthread.html#details
-
Regarding QtConcurrent::run(), while I understand the need to still use mutex locks should the function mutate state somewhere, is there any similar consideration that must be made if the function instead calls the member function of an object pointer it is passed, and passes data through this member function?
Alternately, seems like QFuture would be a safe way to do it also.
-
[quote author="qttester5" date="1397088178"]is there any similar consideration that must be made if the function instead calls the member function of an object pointer it is passed, and passes data through this member function?[/quote]Simply ask yourself: Is it safe to call those member functions from different threads? If yes, then it's fine to run your top-level function through QtConcurrent::run().