Using QThread
-
I have a question about "good practices" using QThread. I have a couple of related functions that I would like to run in their own thread. These function calls are not frequent, but often enough. Rather than create a QThread object for each of these functions, I created a single QThread object. Each method sets a function index and starts the thread. The run() function of the thread checks the function index, then calls that function.
@void myThread::run()
{
switch ( _function )
{
case FUNC1:
func1();
break;
case FUNC2:
func2();
break;
}
void myThread::callFunc1()
{
_function = FUNC1;
start();
}void myThread::callFunc2()
{
_function = FUNC2;
start();
}@Is this a reasonable way to do this? How expensive is start() - should I use a QWaitCondition instead and put the run() function asleep waiting for the condition?
-
Look into QThreadPool and QRunnable.
Qt maintains a global instance of QThreadPool with ideal threadcount. Thread creation is expensive and hence QThreadpool would provide you with threads which can run your runnables and go back to threadpool. So I'd suggest make your funcs runnables and use it with global qhreadpool instance.
-
Did you have a look at "QtConcurrent::run()":http://doc.qt.nokia.com/4.7-snapshot/qtconcurrentrun.html#run ?
Allows you to run a given function in a Thread. And I think it uses the QThreadPool as well.
Regards,
Markus -
Why don't you make your function public slots of the QThread subclass? You should call, say , in the constructor of the subclass
@this>moveToThread(this);@
This way, your slots would run in another thread than the callee's thread. As an additional benefit, you can enjoy various Signal-Slot connection types (Qt::DirectConnection, Qt::BlockingQueuedConnection etc) besides the default Qt::AutoConection, if needed.
You wouldn't need to reimplement QThread::run().
-
"You're doing it wrong...":http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/
The proper fix is to make an object and move that to a QThread. You cannot move a QThread into the thread it manages.
-
Franzk, technically you can do it, of course not in constructor, but after thread was started.
-
Although technically possible, it would still be a bad idea. Bradley states the following:
bq. My #1 biggest gripe with this code is moveToThread(this); I see so many people using this without understanding what it does. What does it do, you ask? The moveToThread() function tells Qt to ensure that event handlers, and by extension signals and slots, are called from the specified thread context. QThread is the thread interface, so we’re telling the thread to run code “in itself”. We’re also doing this before the thread is running as well. Even though this seems to work, it’s confusing, and not how QThread was designed to be used (all of the functions in QThread were written and intended to be called from the creating thread, not the thread that QThread starts).
Using stuff in a different way than intended usually leads to confusion and without any doubt to errors in the future. To me it would be like placing a table on top of it's own table top...
-
It is possible to do it in the constructor. I have done it many many times, and it works perfectly. Changing the object's thread affinity and starting the thread are two diferent matters.
I have also read the blog entry Frankz quotted. However check what is recommended in the official Qt book "C++ GUI Programming with Qt 4, Second Edition". They recommend using QThread subclasses:
bq. Providing multiple threads in a Qt application is straightforward: We just subclass QThread and reimplement its run() function.
This, although not the same as moveToThread(this) business,
contradicts Bradley's interface separation argument. What do we do now?As when to do this: Sometimes, for me most of the times, you want an object to run all of its functions in another thread: Image processing, logging, image acquisition, io, network comm etc. I want only one instance of an object to run in another thread.
UPDATE: The book covers Qt 4.3, Bradley says there has been changes at version 4.4 that makes using QThread without subclassing it possible. So, I agree with the comments above and recommend using QThread as Bradley suggested:
@myObject->moveToThread(someQthreadInstancePointer)@
Sorry for the confusion I've caused.