I am working on Qt application. There I would like to have worker thread doing some activities in background and I would like main thread to control it, restarting worker thread if it dies for some reason.
I have seen finished() signal emitted by the thread so I guess I could connect slot to it.
Is that the recommended way? If not, how could I achieve that?
If I use finished() signal how can I know difference between normal termination and error?
Thanks and regards
If you want to know whether you had an error or you had the process finished, simply create two signals, not one, and two slots, not one.
In the Qt documentation you have an example there, with a connection to handle the result:
connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
you're here connecting the signal resultReady with whatever method that handles the result. You create another one exactly like this, but with an error signal, and an error handler.
connect(workerThread, &WorkerThread::errorThrown, this, &MyObject::handleErrors);
Of course, another option is to simply pass a parameter with your signals/slots. It's a function call, and if you put some enum with that for the status or some int, that'll do.
Related
I have set a break-point on a slot method and started up gdb to debug my Qt5 application. I would like to know from where in the code this slot gets called from (via the Qt5 signal system).
My naive approach ends in suspension of the program at the break-point, but the stack-trace is all Qt5 internals with no clue as to which part of the program actually sent the signal to this slot (or weather it was a queued or direct invocation:
Is this at all possible? How?
Thanks!
UPDATED
The only time you won't see the signal caller in the stack backtrace is when the connection is queued.
For direct connections you should see something like this:
0 Receiver::baz() <-- slot function that received the signal
1 Receiver::qt_static_metacall()
2 QMetaObject::activate()
3 Sender::bar() <-- function with the name of the signal
4 Sender::foo() <-- function that called emit
5 QWidget::event()
...
For queued connections, the situation is more complicated. But you can add the following to your slot:
QString __sender__ = sender()->metaObject()->className();
This will give you class name of the object, which had sent the signal. You can make it into a macro and sprinkle in your code.
Alternatively, if you have multiple objects of the same class and you need to know which one had sent the signal, you can use the sender() function and compare object address, etc.
Guessing that the signal and slot are connected through a Qt::QueuedConnection, I usually put a breakpoint in every emit of a signal connected to that slot in that case, if there aren't too many of them.
If you otherwise temporarily make it a Qt::DirectConnection (or Qt::BlockingQueuedConnection if across threads) you should be able to see the emission in the stack trace of the emitter thread, waiting for the slot to complete.
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.
I have some problems with Qt. I have a class with a signal who's parameters are strings, and a slot. I'm connecting the signal to the slot in the class constructor. Also, I'm creating a thread in the class constructor. The thread reads data from a server and updates the UI(emits the UpdateMe signal). This is how I connect the signal to the slot:
QObject::connect(this, SIGNAL(UpdateMe(string, string)), this, SLOT(ModifyUI(string, string)));
I have a QTreeWidget with some file names. When I rename a file I notify the server and the server notifies the other clients. When I connect a single client there is no problem, but when I connect more than one client a problem appears: when I notify the server from the second client(when I write into the socket) the following error appears:
QObject::connect: Cannot queue arguments of type 'QVector<int>'
I tried to register QVector with qRegisterMetaType but I also have a signal that is emited when I modify an QTreeWidgetItem(when I rename the item, for example) and I need to dissconnect this signal when I want to change the item's text. If I register QVector I can't dissconnect this signal and the signal is emited.
When you register the QVector, does your call look like this?
qRegisterMetaType<QVector<int> >("QVector<int>");
Once you make this call, you should be able to emit the QVector type over queued connections.
If I register QVector I can't dissconnect this signal and the signal is emited.
Registering a metatype shouldn't prevent you from disconnecting a signal. It just allows you to queue types that aren't already registered with the meta system.
Most of the time, errors which look like this seem to be a result of mixing up threads, and specifically with this one, in my (limited) experience, a result of attempting to manipulate GUI elements "held" in the GUI thread using commands run a worker QThread.
I say "held" because quite often you get a complaint/error/crash saying something like "QObject: Cannot create children for a parent that is in a different thread." (i.e. the GUI thread).
The solution: from a non-GUI QThread ALWAYS communicate with GUI elements using signals and slots.
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.
I am signaling my Qt GUI thread from a boost::thread, and I am using a Qt::QueuedConnection,
connect(src, SIGNAL(signal-signature), dest, SLOT(slot-signature), Qt::QueuedConnection);
and still, when I emit the signal my slot does not get called.
edit: I found the problem, it seems that I was connecting the signal later then my call, but I was sure of the otherwise since breakpoints stopped first on the GUI thread at the connect call and then on the dispatch thread that does the emit
ty everybody for the help and ideas :D
Check whether the slot name and signal name are correct. Usually, if there is a problem (incorrect name), this is signaled in the console (an error message). Also, you could check the result of the connect function call. It should return false in case of connection unsuccessful.
I would assume both threads need to be QThread with a QEventLoop to have that work.