In Qt Application code Class A has one member method like method1(). I want to call this method in another member function method2() and run mehtod1() in a different thread. But what I found from the qt documentation is follows.
Inherit a new class MyThread(suppose) from QThread.
Override the function method run() with your required code.
Create an object of MyThread in Class A and then call the run function wherever you want.
But the above seems bit complex. Is there any mechanism in Qt so that I can create a new QThread(without inheriting) instantly in my method1() and run the method2() with this thread and then return to method1() after execution finishes?
Please let me know if I am not clear in my question.
Yes there is a way like you want.
This article will help you to understand why it's not the correct way to inherit from QThread: https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
This article will help you to know how use QThread in a real simple way: https://www.qt.io/blog/2006/12/04/threading-without-the-headache
You can use QObject slots and signals or event support, combined with threads.
Basically, a QObject's slots called through signal/slot mechanism are executed in the thread that created the QObject. You can also move the object ownership from one thread to another using QObject::moveToThread.
You can also use QCoreApplication::postEvent to post events for execution in the thread the object was created in.
See more about threads and QObjects in Qt documentation ("Threads and QObjects" topic in index).
Going to your problem, you can use two separate objects in different threads to "spread" the execution.
Related
I wish to pass an object using the signal/slot mechanism between threads in Qt. Since I will be passing a pointer to the object, is it safe to call the methods on the object on the receiver's side?
According to this question question the object is not copied (so using original object).
Is this safe? Or am I executing methods on an object belonging to one thread in another thread? Is there a better way to do this?
(I have approximately 20 getters in this class so I don't want to pass individual variables, as well some of the variables are in fact pointers to objects as well)
It is not necessarily safe - signals and slots can be used to cross thread boundaries, so it's possible you could end up trying to access the object from another thread.
The thread in which the slot will be called is determined by the connection type. See the documentation, but as an example:
connect(source, SIGNAL(mySignal(QObject*)), destination, SLOT(mySlot(QObject*)), Qt::DirectConnection);
In this case the function mySlot() will be called from the same thread that the mySignal() signal was emitted in. If your object is not accessed from any threads other than the same thread as the signal emitter this would work fine.
connect(source, SIGNAL(mySignal(QObject*)), destination, SLOT(mySlot(QObject*)), Qt::QueuedConnection);
In this case the function mySlot() will be queued, and called by the event loop of the destination object. So anything done to the object, would happen from within the thread running the event loop of the destination.
I personally find it's best to just stick to passing simple values as arguments. Even though this can work, you would need to add suitable multithreading guards to your QObject if it's likely to be accessed from multiple threads.
First of all, try to use QtConcurrent when you are developing a multi-threaded application. The QtConcurrent namespace provides high-level APIs that make it possible to write multi-threaded programs without using low-level threading primitives such as mutexes, read-write locks, wait conditions, or semaphores.
After that, safety depends on your class members. If all members are thread-safe, then all will be run safely.
When using a QML WorkerScript, are the requests (sent via postMessage()) queued (and executed on a single handler thread) or is there the possibility/danger that two successive postMessage() will be executed on two threads concurrently?
Short answer
All WorkerScript should execute in the same thread.
Not so short answer
All WorkerScript in a QQmlEngine should execute in the same thread.
Long answer
When you create a WorkerScript in QML you instantiate the QQuickWorkerScript C++ class. This class uses the QQuickWorkerScriptEngine class to handles all the thready things.
Now, if you look at QQuickWorkerScript::engine() and QQmlEnginePrivate::getWorkerScriptEngine() you will see that all WorkerScript objects will share the same QQuickWorkerScriptEngine instance as long as they share the same QQmlEngine.
Also QQuickWorkerScriptEngine is a QThread (public inheritance) and contains a member variable named d of type QQuickWorkerScriptEnginePrivate *. d is running in the thread handled by QQuickWorkerScriptEngine (see d->moveToThread(this) in QQuickWorkerScriptEngine constructor). And it is this d that will effectively run the asynchronous work in QQuickWorkerScriptEnginePrivate::event().
PS
This kind of contradicts Qt documentation that states:
Use WorkerScript to run operations in a new thread.
Which might make you think that each WorkerScript is a new thread.
So I have been using QtConcurrent::run for some time and its fantastic. But now I need the function to return an object. Therefore I use the pseudo code
QFutureWatcher<MyObject> fw;
QFuture<MyObject> t1 = QtConcurrent::run(&thOb, &MythreadObjFunc::getList, ConSettings, form, query);
fw.setFuture(t1);
// Both .results() and waitForFinished() block
fw.waitForFinished();
MyObject entries = t1.result();
Then I iterate through the myObject. The issue is that this is blocking e.g. my main GUI is not responsive. And this was the whole reason I started using QtConcurrent::run
Therefore, what is the recommended way to have my GUI execute a QtConcurrent::run and get the object back but not block? I thought of signals and slots where the signal would be from the QtConcurrent::run but this would mean that it would be from a different thread and I read thats not recommended.
Thanks for your time.
You should never use any waitForFinished functions in the GUI thread. Instead, connect a slot to the future watcher's finished signal. See this answer for an example.
From QtConcurrent::run() you can't emit any signal. Runnable function is not a QObject. That is the first thing.
The other thing is that QFutureWatcher::waitForFinished() blocks the execution until the thread ends its execution. This is the intended behaviour. If you have to wait for your function to finish, why do you even launch it on separate thread? It makes no sense.
The easiest solution would be to make your function a member of QObject-inherited class, move the instance to the other thread, launch the calculations and emit done() signal. Qt's signal and slot system is thread-safe and it is the perfect way to use it. There is a outstanding documentation provided by Qt that covers this subject more than enough. You should start reading here: http://qt-project.org/doc/qt-4.8/threads.html
I have been a Qt programmer for quite some time now and i understand most of the general features of Qt. I am still confused about how the connect statement connects a signals to a slot at run time. Basically i would like to understand what happens at compile time and what happens at run time..
compile time: meta object compiler will generate code to implement a signal in an additional cpp file (one for each class containing Q_OBJECT).
run time: signal is mapped to a slot, slot gets executed? this is the part i am not clear about...SIGNAL and SLOTS are macros that expand to string representation of the signal/slot names...how does this and the meta object help in mapping calls to slots at run time? details would be appreciated...
EDIT:
this link will give you a better idea..(only if you are interested in the gory details...)
http://dev.libqxt.org/libqxt/wiki/Meta_Object_Format
couple this with the documentation of QMetaObject and things should become clear...
There are various ways you can connect a signal to a method (signal/slot).
However, they all revolve around getting the correct method number.
After you have the correct method number and the object to call it on, you simply call a virtualized function (qt_metacall) in QObject which finds the correct method to call from the number given. You can find this function in the files that the MOC generates. Also, in that generated file, you can find a line which creates a static QMetaObject of your class. This object registers the names of your slots and signals to the method numbers.
These might provide some interesting stuff to read:
http://doc.qt.io/qt-5/qmetaobject.html
http://doc.qt.io/qt-5/metaobjects.html
http://doc.qt.io/qt-5/signalsandslots.html
You can also learn a lot by running thought the slot activations with a debugger.
Basically signals and slots work similar to messages in Objective-C.
The macros cause the preprocessor to replace them with some code which "registers" and "looks up" the functions/methods that are to be effectively executed when a slot is called.
This allows for more flexibility, because the code that is emitting a signal or calling a slot does not need to know much about the other code modules which use them. Each slot and signal generate a signature that is looked up at runtime and then called.
If you are familiar with C/C++, you can compare this to dynamic libraries. Symbols are looked up at runtime and their address is then used to let the CPU "jump" to them to execute.
Also, these links might help you:
Qt question: How do signals and slots work?
http://doc.qt.io/qt-5/signalsandslots.html
Can a class inherited from QThread and having run method can have other methods and can it be used like another normal ( not inherited from QThread) class?
Yes, a class that inherits from QThread is still a normal class. However, care must be taken to synchronize calls to member functions that occur in a different thread context (i.e. calls from outside of the run method) as necessary. Read about Thread Support in Qt for more details. Herb Sutter has a nice collection of articles discussing different aspects of concurrency as well.