i am at the moment really confused about threading in QT. I read so much different opinions which i can realize this.
I have a class (Computations) which do heavy computations and generate a lot of solution. When this class find a solution i call with help of
boost::function<void (Solution)> f;
a custom function. Which can be bind with
f = boost::bind( &MainWindow::FoundSolution, this,_1);
No i have my mainwindow in QT. There i call my class Computations with
Computations comp(f);
QFuture<void> future = QtConcurrent::run(comp,&Computations::DoSomethink);
So it compute while i can use the GUI and i get the response of new solutions to the FoundSolution function in my mainwindow. In this function I use QGraphicview to draw my solution. The Qgraphicsview is a member of my Mainwindow.
This works sometimes.
But i often get the following error
Assert failure in QCOREApplication::SendEvent: " cannot send events to
objects owend by a different thread. Current thread 438bc40. Receiver
" (of type "Qgraphicsscene) was created in thread 15dcc00, file
kernel\qcoreapllication line 494
This mean i call my GUI application from a thread which is not the main and this is forbidden by QT. But with my boost bind i should be in my main thread or? And why it works sometimes ?
Do you know a better implementation for this? I am really new with QT and threads.
Thank you for your help.
If you emit a signal from you worker thread that is connected to a slot of an object that lives in the ui thread, the slot will be executed in the ui thread.
So basically if you want to draw a new point in the QGraphicsView, send a signal from your worker thread passing in the coordinates of the new point to draw. The signal need to be connected to an object that lives in the ui thread. The slot will then handle drawing the new point in the QGraphicsView which will work since the slot is executed in the ui thread.
For more information see Signals and Slots Across Threads
The normal way to do this is to use signals and slots. You can find some documentation, which is specific to your problem, here: Qt 4.8, Qt 5.
connect( &sender, SIGNAL(), &receiver, SLOT(), Qt::QueuedConnection)
The easier fix is to add Qt::QueuedConnection to the problematic slot connection call.
Related
I have the follow constellation:
A qt gui thread with MainWindow
Another thread which essentially is a CameraManager...everytime a camera is added/removed the MainWindow will be informed.
It roughly looks like this:
Mainwindow derives from ICameraAddedConsumer
MainWindow implements ConsumeCameraAdded and creates widget inside this function. It subscribes itselv as a consumer to the CameraManager
CameraManager calls ConsumeCameraAdded of all it's consumers (MainWindow) when a new camera is added.
The problem is that CameraManager lives in a different thread and Qt will obviously complain about this since a widget is not created in the same thread as the mainwindow was.
Any suggestions how I can solve this?
As per comments, using signals/slots between QObjects in different threads should take care of the issue "automagically."
Barring that, and assuming MainWindow/ICameraAddedConsumer is a QObject, one idea could be to use something like:
QMetaObject::invokeMethod(consumer, "ConsumeCameraAdded", Qt::QueuedConnection, ...)
where consumer is a pointer to the MainWindow/ICameraAddedConsumer instance.
There's QWaitCondition but I'm not sure that makes sense in this case (though it could be adapted I suppose).
Otherwise... don't create the widget in ConsumeCameraAdded() but set some flag there (and return) and then use a QTimer or QObject::timerEvent() to periodically check the flag and create widget if it is set. Unfortunately I'm pretty sure you will not be able to create or start a timer within ConsumeCameraAdded() itself because of threading issues.
I know that normally you wouldn’t do what I’m asking. I understand that these two layers should be separate and connect via signal/slot mechanism, which maybe asynchronous if we deal with threads.
Understanding this, I still need to call qml signal handler synchronously from SG thread. Qml objects live in GUI thread, thus emitting a signal from SG thread (particularly from updatePaintNode() method) results in asynchronous event.
I have read docs and I have no problem calling qml function synchronously from cpp from another thread. For example:
QMetaObject::invokeMethod(this, "myNiceQmlFunction", Qt::DirectConnection);
But imagine this:
//some.cpp
signal void callQmlHandler();
//some.qml
MyObject {
onCallQmlHandler: {
// do something right now
}
}
I don’t know how to call onCallQmlHandler synchronously via QMetaObject::invokeMethod.
I don’t create qml object from code and at this point in cpp I don’t have access to qml component to look for its children, find MyObject there by name and call its handler (if it is possible). Anyways, this is not a beautiful way to do so.
I tried to find signal handler among QMetaObject methods, but it's not there. Nor it is in properties list (I checked just in case, because syntax of signal handlers is similar to property's one)
Does anyone know if I miss the right syntax to call signal handler via QMetaObject::invokeMethod or it is not possible at all? Any ideas?
You can pass a C++ object to QML using its context.
qmlviewer.rootContext()->setContextProperty("backend", backend);
QML side:
Connections {
target: backend
onCallQmlHandler: {
// do something right now
}
}
When you emit callQmlHandler from backend object, you get the handler executed.
But Connections object may create queued connections, so you can implement your own DirectConnections. At the end of this post you have an implementation.
However QML is excecuted by a QML engine, which I think is intended to be run by a single thread, so you may run into a bigger problem unless you really know what you are doing!
I am writing a mathematical simulator in Qt5 and when I click a button, some heavy calculation needs to be done. During it, I want to display a Please, wait window, eventually with a progress bar. Preferably without using threads.
Problem is, during calculation the application hangs, events are not handled, and what should be a please, wait window is merely a window frame without any contents (looks transparent).
PC: AMD X2 L325, 2GB RAM, Radeon E4690
OS: Debian 6 (Squeeze, Old stable)
gcc 4.4.5, Qt 5.2.0
Any help would be appreciated!
While you could call QApplication::processEvents, it's not the best approach.
If you're avoiding threads because they're new to you, then I'm sure you'll find it much easier once you've done it once. Qt makes it easy.
All you need to do is create a class derived from QObject which will do the calculations. Next, create a thread and call the object's moveToThread function. The thread is then controlled with a few signals and slots. That's all there is to it.
Rather than repeat the content here, I suggest you read this article, which explains it in detail and provides clean and concise example code.
From the new object that processes your calculations, it can then emit a signal to a slot on the main thread, which will update the progress on your "Please Wait" window.
Note that Widgets and all rendering must be done on the main thread.
I prefer use Qt Concurrent. It is not well documented, but very handy, much better then using QThread directly.
I usually do such things like that I have separate QObject for logic, in there some slot which calls heavy calculation like that (see run documentation):
void MyCalculationClass::startCalculating() {
QtConcurent::run(this, &MyCalculationClass::doHeavyCalculation);
}
Where method doHeavyCalculation emits signals with progress and calculation results.
Usually this method operates on its own data not modified by other threads/methods, so if synchronization is needed, it is trivial. Signal-Slot mechanism is handling most of the multithreading issues (note that default connections detects that signals is emitted from other threads and queues slot calls in proper thread, it is done automatically by default).
i have such problem and i solve it like this, i make calculation in another thread( i use std::thread instad of QThread) before i start my calculation i just start timer
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(repaint()));
timer->start(1);
and then
std::thread t(&Widget::calcBackgound, this);
t.detach();
You can put the heavy and time consuming part of your code in run() member function of another class which inherits from QThread. After that create an instance of the new class and simply call its start() function.
Your new class can have a signal which emits the current progress value. you can then connect this signal to the slot of a progress bar.
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.
I created a multithreaded application in Qt (4.7.2). Only the main thread has an event loop.
The issue is that sometimes I get the following warning in the console:
QObject::startTimer: timers cannot be started from another thread
After this happens, the app consumes 100% of CPU (I have a single core CPU). It seems, that the main thread consumes all of the CPU's resources. The program does not freeze, and everything still works.
When I stop the program in the debugger, I do not see my code in the call stack.
The problem is that I'm not using (explicitly, anyway) timers at all.
What could it be connected with? I know, that question is very common, but I can't even understand, what piece of code to show.
Thanks, to #vrince I've fixed the problem. I used signals/slots mechanism + Qt::QueuedConnection to communicate with GUI
For example, if I need to set text of QLabel from worker thread, I can make in my worker thread signal
void textChanged(QString);
then I connect this signal to the slot of QLabel using Qt::QueuedConnection
connect(worker, SIGNAL(textChanged(QString)), label, SLOT(setText(QString), Qt::QueuedConnection);
If I want to execute setText synchronously, I can use Qt::BlockingQueuedConnection
now in my worker thread I just emit signal:
emit textChanged(newText);
Also, it is possible to use QMetaObject functions to avoid signals and slots:
metaObject->invokeMethod(label, "setText", Qt::QueuedConnection, Q_ARG(QString, text));
One of several initially baffling PyQt "warnings" (with consequences) symptomatic of a single, classic cause: trying to manipulate GUI elements using a non-"application thread", without using signals and slots as you should.
See my answer here.