I will try to explain what my program used to do and what I am tring to change:
I had this function that ran on a button click from the the main thread in class MainWindow : public QMainWindow :
The function looks like this and is specified inside another file:
void MakeMeshStructure(MeshStructureLayers layers,
Handle_AIS_InteractiveContext theContext,
Handle_TDocStd_Document aDoc,
MyMesh &mesh,
int detail_vertex,
double insulation_thickness,
OpenMesh::VPropHandleT<MyMesh::Scalar> _max_beam_offset);
}
What it does is: it works on mesh and creates geometry for every vertex, face and edge of the mesh. This geometry gets displayed with theContext. This process takes very long (30 min) and blocks the gui.
What I would like to do is to have as many threads as QThread::idealThreadCount() and to free the gui when it computes and make it faster. (Is this the right thinking?)
I would like to divide my mesh into equal parts and pass this range of vertices to my function (above) to only work with one vertex range for a seperate tread.
I have a problem to figure out how to pass this data around and to make it thread safe.
I know its alot of code but here is my attempt at solving it:
http://pastebin.com/u/mzagar
The problem is getting all the data around in the right way and getting the threads to work. Where do I have to use mutexes. On every data that can get writen at the time of the thread work by the mainthread? Very confused. ty
edit:
I edited my code: http://pastebin.com/u/mzagar
I made a struct cadData to pass the data around. This is how I start threads:
connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
//...
emit startMake1(aCadDatas.at(0));
//...
The problem is threads dont seem to work at the same time and also the gui freezes. Process goes in like this:
GUI freezes
things in thread 1 get done
things in thread 1 get done again
things in thread 2 get done
things in thread 2 get done again
...
GUI unfreezes
Any ideas why?
edit2:
I removed the multiple runs of the same thread by moving this to the class constructor:
connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
Since you're using QThread, you can probably avoid explicit use of mutexes and such by using Qt's thread-safe slots-and-signals mechanism to do the work for you. You would basically package the data you need to send to the thread into an object, then emit a signal that has that object as an argument. The thread would receive a copy of that object in a slot (that you had previously connected to your signal) and start using the data then. To get data back from the worker thread to the main thread, you'd do the same thing again in reverse. Here's an article with some example code.
To add to Jeremy's answer: You can do the same by sending events between QObjects instead of using the signal-slot mechanism. Use whichever is most convenient for you.
The key is to leverage Qt's built-in event loop mutex. When you're sending signals to objects living in a thread different from the sender, the signal gets converted into a QMetaCallEvent and is posted to the event queue of the receiving QObject. This is done in a thread safe manner of course, and all one has to do is to leverage it. Sending explicit events works the same way. The event loop spinning in the thread where the receiver lives simply picks up QMetaCallEvents and executes slot calls accordingly, or dispatches your events to your implementation of customEvent() method.
When you start a raw QThread, the default implementation of the run() method spins up an event loop. You'll notice that such a thread is effectively idle and does not consume any CPU resources: the event queue is empty, and the event loop is blocked, waiting for someone to post an event to its queue. Once you move some QObjects to such a thread, the queued signal-slot deliveries will be done via the event loop of that thread. It works the same whether it's the GUI thread, or any other thread. The GUI thread is not special in any way when it comes to receiving events or queued signals.
Related
My first naive at updating my progress bar was to include the following lines in my loop which is doing the processing, making something like this:
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
//Added these lines but they don't do anything
ui->progressBar->setValue(numberProcessed++);
ui->progressBar->repaint();
}
I thought adding the repaint() would make the execution pause while it updated the GUI, but apparently it's not that simple. After looking at the questions:
QProgressBar Error
Progress bar is not showing progress
it looks like I'm going to have to put the data processing in a different thread and then connect a signal from the data processing thread to the GUI thread to update the progressbar. I'm rather inexperienced with GUIs and threads and I was wondering if anyone could just point me in the right direction, ie what Qt classes should I be looking at using for this. I'd guess I need a QThread object but I've been looking through the QProgressBar documentation but it doesn't bring up the topic of threading.
As #rjh and #Georg have pointed out, there are essentially two different options:
Force processing of events using QApplication::processEvents(), OR
Create a thread that emits signals that can be used to update the progress bar
If you're doing any non-trivial processing, I'd recommend moving the processing to a thread.
The most important thing to know about threads is that except for the main GUI thread (which you don't start nor create), you can never update the GUI directly from within a thread.
The last parameter of QObject::connect() is a Qt::ConnectionType enum that by default takes into consideration whether threads are involved.
Thus, you should be able to create a simple subclass of QThread that does the processing:
class DataProcessingThread : public QThread
{
public:
void run();
signals:
void percentageComplete(int);
};
void MyThread::run()
{
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
emit percentageCompleted(computePercentageCompleted());
}
}
And then somewhere in your GUI code:
DataProcessingThread dataProcessor(/*data*/);
connect(dataProcessor, SIGNAL(percentageCompleted(int)), progressBar, SLOT(setValue(int));
dataProcessor.start();
You need to call QApplication::processEvents() periodically inside your processing loop to let it handle UI events.
As Georg says, Qt is a single-threaded co-operative multitasking environment. You get full control of your process until you relinquish it voluntarily with processEvents() - until you do that, Qt can't update the UI elements, handle async HTTP requests, handle input, or pretty much anything else. It's up to you to make sure that stuff gets a timeslice while you're in a long processing loop.
You can create a sub-class of QThread that emits a signal progressChanged, which you connect to the QProgressBar.
connect() makes the connections auto connections per default. That means that the signal-slot-mechanism already takes care of the threading issues for you, so you don't need to worry about that.
I am new to Qt. I have worker thread that is an std::thread. The worker thread function continuously fetches some some data in a loop. The size of the data is frequently updated on a Text element on a QML UI. I have a listener callback which is nothing but an std::function and it gets called from the thread's function. It sends me callbacks based on which I updated the Text element on QML. I update it using signal slot mechanism.
Following is the QML : Text element:
Text {
id: mytext
objectName: "mytextobject"
function slotUpdateData(someValue){
mytext = someValue
}
}
SignalUpdateData is connected with slotUpdateData which resides on QML side. Every time I get the data event callback from the std::thread, I emit SignalUpdateData which updates the QML Text element on UI.
void CallBackReceivedFromWorkerThread(float someValue) {
emit SignalUpdateData(someValue)
}
Following is how I have connected this C++ signal with the QML slot
QObject::connect(this, SIGNAL(SignalUpdateData(QVariant)), myTextItemQObject, SLOT(slotUpdateData(QVariant)));
And all of this works fine. No crashes, lock-ups, nothing.
As per my understanding, since the worker thread's function is triggering the callback, the execution control is on the worker thread when the callback is received. So when doing emit SignalUpdateData(someValue), we'er still on the worker thread. And as far as I know from my previous experience in android & java, we cannot update the UI from anywhere outside the main thread of the application.
So, How is this working ? Is emit SignalUpdateData(someValue) putting the call into the main UI thread's event loop ? Is Qt still making the UI change on main thread in spite of me calling for it from a worker thread ? If my approach is fine, then does it have performance implications ? What is the best recommendation to do this ?
I want to be very sure about this & not just lucky about making this to work. Should I use a Qt::Connection_enum as well for best approach ?
You're leveraging Qt the way it was meant to be! And you've run into it accidentally: that's a sign of a decent design - it "just works". Hooray for you, hooray for Qt :)
It's working because Qt has been designed specifically to make it work, and you're using the default automatic connection whose raison d'ĂȘtre is to help you out in this specific case. So you happen to be doing everything right: change nothing!
When you emit a signal, Qt acquires relevant source and destination object mutexes, and compares the receiving object's thread() to QThread::currentThread(). If they are identical, the slot/functor is called immediately: it happens in the body of the signal, so the slot is called before the signal returns. This is safe as the target object is used from its thread(), where it's safe.
If target->thread() != QThread::currentThread(), then a QMetaCallEvent is queued to the target object. The event contains the (equivalent of) slot method pointer and a copy of any parameters passed by the slot. The QObject::event implementation handles the event and executes the call. The target object thread's event loop is on the call stack, since its job is to deliver the queued events to the object.
The above is, in a nutshell the meaning of a Qt::AutoConnection. If you're using Qt::QueuedConnection, the 2nd case applies no matter what the threads are. If you're using Qt::DirectConnection, the 1st case applies no matter what.
My guess is that >95% of the uses of a non-automatic connection type in Qt-related questions on SO are unnecessary and stem from lack of understanding and resorting to what amounts to magic incantations.
Does Qt offer functionality to know the number of queued signals that are pending for a given slot to process? Is there a way to clear them? For example, if several emits are done on a signal connected to a given slot, how could someone know the amount of these emitted signals?
QMetaObject::Connection class has a laconic interface and does not seem to offer related functionality. Deleting the object that receives the signals, hence destroying the connections, solves the problem. But is there a way to do this without disconnecting the slots or deleting the receiving objects?
The reason you ask the question most likely indicates that your design is broken. The signals and slots are a mechanism to decouple code. The objects connected together should behave themselves no matter how many senders or receiver are there, and certainly shouldn't attempt to track such matters!
It'd be wiser to fix the issue at the source by altering the design. If you are uffering from an event storm e.g. due to changing a widget's data in a slot, the slot should be very lightweight and only schedule an update of the widget by calling update(), but never forcing an immediate repaint. This leverages repaint event compression done by Qt. You might wish to compress your own events too.
Connection types in Qt
Signals and slots in Qt can be delivered using a direct, queued or blocking connection. The automatic type is not really a fixed connection type. It is an instruction to resolve the type for every receiver, at every signal emission into either a direct or queued type.
The direct connection is like any indirect function call: nothing is queued, and the slot is called from within the body of the signal method:
// all direct-connected slots/functors are invoked before mySignal() returns
emit mySignal();
The queued connection posts a QMetaCallEvent to the receiving object thread's event loop. That event contains the arguments of the call, or carries the functor. Is is handled by QObject::event(). You can certainly intercept such events. For details, see this question.
As far as I know, it is not possible to access the queue.
First of all, if the slot is in a QWidget subclass, in the GUI thread, then you can just update the member variables and call update(), and then just use the current values in paintEvent() when it gets called. These are automatically compressed, so there will be just one repaint event, no matter how many times update() gets called.
However, if the slot is not related to painting, or not in the GUI thread at all, then you need something else.
A simple solution to many cases needing this is to use a 2nd slot and a single-shot QTimer with delay 0 (or even longer delay if desirable).
Here's some example code, which should give you the idea of what I mean:
// in constructor, set mActualSlotTimer to
// singleshot, interval 0, parent this (needed for multi-threaded use)
// and connect timeout() to privateActualSlot()
// public slot for receiving the signal from outside
void MyClass::actualSlot(int data) {
// class member to store the new data value until it can be set
mNewData = data;
// restart the timer, no matter if it was already running or not
mActualSlotTimer.start();
}
// "private" slot for actually doing the change
void MyClass::privateActualSlot() {
// maybe useful: if (this->mData == this->mNewData) return;
mData = mNewData;
// do whatever else needs to be done!
}
Obviously, if your public slot does not actually take any parameters, then you don't need mData and mNewData.
One thing to note about this approach is, it works on all connections, it's not limited to just Qt::QueuedConnecton. As a consequence, it also makes using Qt::BlockingQueuedConnection kinda pointless.
A disclaimery note: I briefly checked Qt source code and it seems using timer with interval 0 should be ok: restarting the timer will work as expected. But if there still seems to be too many calls to privateActualSlot, then providing a suitable interval might be necessary. I have usually wanted a little delay (5 ms for example) to throttle things down a bit more than "as often as possible", so have not tested this extensively with interval 0.
I am wondering how to tell a QObject to process all signals and call the slots associated with them. Here's the concrete problem I am having, for a better description of the question:
My program consists of three Qthreads : Main, Communication and Input.
The communication thread handles communication via the network, the Input thread handles user input, and both have several signal-slot connections to the main thread. Whenever a network event occurs, or whenever the user inputs a commandline command, a signal from the respective thread is called, which then activates the appropriate connected slot in the main thread. The main thread's role is to process these events. My code looks as follows:
QApplication a(argc, argv);
CommObj co; //inherits from QThread
co.start(); //Starts the thread
InputObj io; //inherits from QThread
io.start(); //Starts the thread
MainObj u(&co,&io);
return a.exec();
Now, what I want to achieve is for the main thread to not reach the last line.
My intentions are to call a method run() within the constructor of MainObj which is going to do something along the lines of this:
void run ()
{
forever
{
//process all signals..
}
}
However, I do not know how to implement the process all signals part. Any advice on how this could be done (including workarounds) would be very welcome.
This is completely unnecessary. a.exec() runs an event loop that will receive and process the events sent by other threads.
When a slot is invoked due to a signal being emitted in a different thread, Qt is posting a QMetaCallEvent to the receiver object. The QObject::event method is able to re-synthesize the slot call based on the data in the event.
Thus, you need to do nothing. a.exec() does what you want. Feel free to invoke it from MainObj's constructor, as qApp->exec() or as QEventLoop loop; loop.exec(), but that's rather bad design.
The real questions are:
Why do you need MainObj's constructor to spin an event loop?
What sort of "user input" are you processing in the io? You can't access any GUI objects from that thread.
Why are you deriving from QThread if you're using Qt's networking? You definitely don't want to do that - it won't work unless you spin an event loop, so you might as well just use a QThread without changes. Well, to be safe, you need just to make the thread destructible, so:
class Thread {
using QThread::run; // make it final
public:
Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() { requestInterruption(); quit(); wait(); }
};
Anyway, by not using standard QThread that spins an event loop, the communication will be one way. Nothing in such threads will be able to react to signals from other threads.
You need to rearchitect as follows:
Use the Thread class as above. It's safe to be destructed at any time.
Have worker objects that run asynchronously using signals/slots/timers.
Move constructed workers to their threads.
What you need is the processEvents function. For example, if you don't want the user to be able to interact with widgets, but you want the graphics to update, use
processEvents(QEventLoop::ExcludeUserInputEvents);
See the documentation for details.
i using qt5 and opencv to create an application that give a user inteface using qt and does the image processing part in opencv.....
so far my design is:
i am displaying a video and some standard controls like buttons and checkboxes using qt main gui thread
for capturing image and processing it, i have created a worker class derived from QObject and moved it to a thread....
the function that is executed in the worker class(Worker::process) has a blocking while loop.....that constantly:
captures a frame from a video or a camera
does some processing on it
converts from cv::Mat to QImage
emit a signal to the main thread to display the QImage
also in order to recieve user input i was using emitting signal from the main thread to the worker slots
the problem i faced was that the signal from the main thread never got picked off by the worker because of the event loop blocking while loop.
after much searching i came up with the solution to use Qt::DirectConnection argument while connecting the signal from the main thread to the worker slots. that solved the problem at that time.
now i need to add a qtimer or qbasictimer inside the blocking while loop....and guess what, the timer slot(in the case of qtimer) and the protected timerEvent handler (in the case of the qbasictimer) never get called. my hunch is that again the blocking while loop is the culprit
after much searching and reading on forums i have come to the conclusion that somehow my over all design maybe incorrect.....and as i keep adding more functionality to my application these problems will keep showing up.
I have two options now:
somehow call the threads exec() function inside the blocking while loop. so the question to the gurus out there is:
"how do i call the thread::exec() method inside a worker QObject class, i need the reference to the thread running the worker to call exec()" (short term solution)
change the whole implementation.....and here the questions is:
"what are my options....." (long term)
please feel free to ask for details in case my wording or english has made the problem unclear in any way.....thanks...
Inside your worker's blocking loop, call qApp->processEvents(); periodically.
http://qt-project.org/doc/qt-5.1/qtcore/qcoreapplication.html#processEvents
#include <QApplication>
// ...
void Worker::doWork()
{
while(true)
{
someLongImageProcessingFunction();
qApp->processEvents();
}
}
This should allow for the slots to get processed, and for the timers to update.
Using a direct connection may let you access and change values local to your worker, but you should be careful about thread safety. If you put a QMutexLocker right before your values that get modified by your GUI and right before your worker thread uses them, you should be good.
http://qt-project.org/doc/qt-5.1/qtcore/qmutexlocker.html
Also if you wanted any of those slots to run on the worker thread, you need to use the QueuedConnection.
http://qt-project.org/doc/qt-5.1/qtcore/threads.html
http://qt-project.org/doc/qt-5.1/qtcore/qthread.html#details
In some parts of the Qt docs it describes subclassing the QThread class. Other parts recommend the Worker/Producer model, and just use connections to setup how you use your threads. Usually there are fewer gotchas with the Worker/Producer model.
Hope that helps.