Force Qt custom signal to be processed immediately? - c++

I have a question about Qt and its signals/slots mechanism.
I have created a custom widget and in that I have created a custom SIGNAL (ShowMessage). This signal is connected to a SLOT, which displays the message (along with the specified timeout) in my main window's status bar.
Now, I have an operation in my class that takes a long time to execute, and it's blocking the UI. I was hoping to emit my signal before starting the operation and when it's finished, emit it again to update the status bar; something like this:
emit ShowMessage(message, timeout);
// Do the long operation
emit ShowMessage(newMessage, timeout);
But my problem is that it seems that Qt waits until the whole operation is finished, and only updates the status bar with newMessage.
Is there a way to somehow "force" immediate processing of my signal, because if I want to resort to threads, then my life will get much more complicated!

Is there a way to somehow "force" immediate processing of my signal
Yes, there is. :-).
After you show your first message, call QCoreApplication::processEvents(). This forces all pending events to be processed at the point of call. For example,
emit ShowMessage(message, timeout);
QCoreApplication::processEvents();
// Do the long operation
emit ShowMessage(newMessage, timeout);

Related

Will UI block when waiting for QThread / How to use QThread properly

If I have a progressbar in the ui thread (window), which shall run endless until a method finishes it's work, will the ui thread block and so the progress bar if I'm waiting for a second QThread to finish? If the ui thread blocks waiting, then i would not to wait for the second thread. I thought to implement a callback method which will be called when the second thread finished, but then: How can i connect to the callback method?
What do I want to do?
I have a window, this window has a progressbar which is first not visible. When the user presses a certain button to request data, a method will be called which returns a RequestPointer which contains a method which returns the request status.
When the user presses the button, i want to make the progress bar visible, running infinitely till the request is finished and i can print the data to the window.
To the Worker i want to pass this pointer and the worker checks in a while (flag) loop, if the status is still running and sleep if so. When the worker finishes, i want to stop the progressbar and make it unvisible again. Do i have to pass the progress bar to the thread, or can i wait for the thread without blocking the ui?
I'm not quite a Qt pro. Really new to it. I tried to get some info from the https://doc.qt.io/Qt-5/qthread.html website, but it's a bit hard for me to understand the code example.
Method in my worker class:
void Worker::watchRequest(RequestPtr r_ptr)
{
bool exit = true;
while (!exit)
{
ErrorCode errorCode = r_ptr->Test();
switch (errorCode)
{
case Request_RUNNING:
QThread::msleep(10);
break;
case Request_ABORTED:
exit = true;
break;
case Request_SUCCESS:
exit = true;
break;
}
}
QThread has a finished signal. Connect this one to some appropriate slot, which will trigger any action necessary on thread completion.
I suppose best candidate to know how far the progress went is the worker thread itself. You might create your own signal that sends the current progress to some slot that will do the update of the progress bar appropriately.
Alternatively, you might use a QTimer to read the current progress from time to time (this resembles closer to what you have now, but does not block the UI).
If you don't want to block the user interface, all you have to do is to call QApplication::processEvents(); in your while-loop.
I have some code which uses std::future instead of QThread and my code looks like this:
while (!progressIndicator->UserBreak()
&& (future.wait_for(std::chrono::seconds(0)) != std::future_status::ready))
{
QApplication::processEvents();
}
This works well.
To update the UI Thread's progress bar while the operation is running, use a QTimer object to increment the progress bar's value (Max value will be :One less than Progress bar's value when the operation completes). Also connect the QThread to a slot by Signal/Slot method to signal the UI thread when the operation has ended. When the QThread finishes the operation, send a signal to a Slot in the UI Thread, which will set the final value of the progress bar and also stop the QTimer.

How can I prevent transmission of execution control to the last executed function when a Qt signal is emitted?

I have a Qt C++ program. I have a main driver MainWindow and a TCPClient class. The TCPClient class is used to communicate with a remote server, transmit some data over TCP, request for processing of the data and receive processed data from server. In my TCPClient class, I am using QAbstractSocket signal disconnected. This is emitted when the connection with the server is disconnected. In the function (slot) which handles this disconnect signal (ifDisconnected), onCompletionCallback function of the MainWindow is called. Now my question is how do I prevent the transmission of execution back to TCPClient after the said onCompletionCallback finishes executing. What's following is incomplete code describing the issue;
mainwindow.cpp
void MainWindow::on_connectButton_clicked()
{
std::function<void(void)> callback std::bind(&MainWindow::onCompletetionCallback, this);
tcpClient_ = new TCPClient(callback)->connectToServer(someData);
}
void MainWindow::onCompletetionCallback()
{
if(tcpClient_->isRequestSuccess())
{
QJsonDocument responseJson = tcpClient_->getResponse();
return; //When this finishes executing, I want to prevent the execution control to go back to TCPClient
}
}
TCPClient.cpp
void TCPClient::connectToServer(QJsonDocument requestJson)
{
// Removed code of other connect signals
connect(tcpSocket_, &QTcpSocket::disconnected, this, &TCPClient::ifDisconnected);
}
void TCPClient::ifDisconnected()
{
// Here the callback is called. After the callback finishes executing, I don't want execution to return to `TCPClient`.
onCompletionCallback_();
return;
}
How do I solve this problem. I need to use the signal disconnected because QAbstractSocket doesn't provide any utility function to check if the connection is available.
You cannot and you should not prevent that the signal handler returns to caller. Otherwise, you would corrupt your call stack.
The actual question (for me) is: What is the caller of signal handler?
To understand what I mean, please, read the Qt doc. about QObject::connect() with special attention to Qt::ConnectionType.
The default is Qt::AutoConnection which means:
If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used. The connection type is determined when the signal is emitted.
Qt::DirectConnection:
The slot is invoked immediately when the signal is emitted. The slot is executed in the signalling thread.
The most common case (for me) are signal handlers called for modifications of GUI objects (i.e. widgets, etc.) which modify data or other widgets in response (in strict single-threading manner). In this case, it is Qt::DirectConnection i.e. the widget signal emitter is the caller of my signal handler.
A possible error (I did once) is to delete the widget which emitted the signal (e.g. handling a close button event of a dialog) – bad idea: I destroyed the widget with a pending method call on call stack. After returning from my signal handler it ended in a crash. The caller method (the signal emitter) had no instance anymore, or in other words: its this was invalidated. (It's like sawing the limb you sit on.) (Btw. deleteLater could be one solution for this. I found SO: How delete and deleteLater works with regards to signals and slots in Qt? concerning this.)
Considering your code sample
connect(tcpSocket_, &QTcpSocket::disconnected, this, &TCPClient::ifDisconnected);
I suspect this is a Qt::DirectConnection.
The other aspect: calling a main window function out of the TCP client thread is something which needs special attention as well. The caller is something in the TCP client thread but addresses an object (the main window) which resides in the (different) GUI thread. Phew. Everything (exept local variables) what is accessed in this called function must be mutex guarded if the GUI thread itself uses this as well.
So, what about the other options:
Qt::QueuedConnection:
The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.
For communication between threads, IMHO, the Qt::QueuedConnection is the safer way: The TCP client emits a signal which results in a respective entry in the event loop of the GUI thread (assuming the main window was given as receiver object). The GUI thread will pick up this entry while processing its event loop. In this case, the event loop of GUI thread is the caller of the signal handler. The TCP client thread didn't wait after sending the signal request but continued its processing. If this is not desired the third option comes into play:
Qt::BlockingQueuedConnection:
Same as Qt::QueuedConnection, except that the signalling thread blocks until the slot returns. This connection must not be used if the receiver lives in the signalling thread, or else the application will deadlock.
The Qt::BlockingQueuedConnection lets the signal emitter (the TCP client) until the GUI thread has processed the signal handler. (The warning about the dead-lock is not effective here as the TCP client thread is the signaling thread where the GUI thread is the receiver.)
I'm a little bit uncertain what to recommend. I'm afraid your application needs a little bit re-design but for this the code sample is a little bit to incomplete.
A possible solution:
Introduce a Qt signal emitted when completion is required. The MainWindow::onCompletetionCallback() may be connected as signal handler to this TCP client signal using a Qt::BlockingQueuedConnection.
If the end of transmission is recognized it may perhaps destroy the TCP client thread. However, a thread which kills another thread is no good idea in general (and I'm not sure how Qt handles this "under the hood"). Therefore, a better concept would be: If the end of transmission is recognized the main thread flags the TCP client thread to leave it's main loop. Flagging could be done e.g. with a std::atomic<bool> (or you stay in Qt which has its own pendant QAtomicInt. The TCP client checks this flag in its main loop or at least after emitting a signal and exits in case.
A last hint:
If you are uncertain whether you understood the all the signal stuff correctly – I checked my understanding by putting a break point into the signal handler and inspecting the call stack when execution stopped at that break point. This is easy and straight forward (except you are dealing with mouse or drag & drop events).

Qt/C++ how to wait a slot when signal emitted

I have developed an app in Qt/C++, I have used signal/slot mechanism to interact between 2 threads. the first thread run the UI/TreeWidget and the second one run the framework
I got an issue on one action.
In the UI side, before starting my action, I'm connect signal/slot between UI and framework such as below in the treewidget.cpp
connect(&m_Framework, &Framework::RequestIfNameExist, this, &TreeWidget::RequestIfNameExist);
connect(this, &TreeWidget::SendAnswerIfNameExist, &m_Framework, &Framework::NotifIfNameExist);
The framework, start and send the RequestIfNameExist:
emit RequestIfNameExist(tmpname, item, fileInfo.isDir());
while(WaitingResponse == false){
usleep(200);
}
I have added a loop because I need to wait the feedback. Strange things is that in the treewidget.cpp, I never enter in
void TreeWidget::RequestIfNameExist(QString name, TreeWidgetItem *parent, bool isFolder) {
#ifdef PULS_LOG
QLOG_INFO() << "[TreeWidget] [RequestIfNameExist] ";
#endif
emit SendAnswerIfNameExist(isNameExist(name, parent), isFolder);
}
I never access to RequestIfNameExist in the TreeWidget but the signal is emitted.
I have also put a while loop in the framework to wait the feedback from TreeWidget
void Framework::NotifIfNameExist(QTreeWidgetItem *item, bool isFolder){
if(item != NULL)
item->isFolder = isFolder;
WaitingResponse = true;
}
Any idea why the signal emitted by framework never arrived on the treewidget ? is it coming from the while ??
Is there a way to not use while such as a "wait event" + timeout
Thanks
My first thought is that having either thread block until an operation in the other thread completes is a poor design -- it partially defeats the purpose of having multiple threads, which is to allow multiple operations to run in parallel. It's also liable to result in deadlocks if you're not careful (e.g. if both threads decide to emit-and-wait at approximately the same time!)
A better design would have the initiating method do the emit RequestIfNameExit and then return immediately, so that the initiating thread's event loop can continue running as usual during the operation. Then, when the other thread has done its work, it responds by emitting its own response-signal, causing the appropriate/connected slot-method in the first thread to be called, at which point the results are handled back in the first thread.
That said, if you insist on wanting to block the execution of the signal-emitting thread inside a method, until the other thread has finished executing the associated slot-method, you can get that behavior by setting the signal/slot connection's type to be Qt::BlockingQueuedConnection (the connection type can be specified via an optional extra argument to connect()). If you do that, then you emit call won't return until the slot-method (in the other thread) has finished executing. Given that, you can get the results from the other thread by passing a pointer to a data object as one of the arguments in the signal/slot method signature, and having the other thread populate that data object as necessary. When the emit returns you can just examine the contents of that data object to see the results.

QT : How to determine if the event processor is busy

In my current Qt application I am attempting to shut it down using
QCoreApplication::quit();
Now it takes more than a minute for the application to shutdown. I believe this is because the event processor of the main form is busy. My question is : Is there a way for me to determine what the cause of this might be. Here are somethings that I suspect
1-Queued Connections.
I have a lot of queued connections. Maybe some of those connections dont get processed
2-Event Loop.
May be the event loop is busy doing something that I dont know (expect)
Any suggestions on what I could do to check why the app takes so long to close ?
Update:
I tried QCoreApplication::hasPendingEvents() and that returns true
There's no such thing as queued connections that are "not" processed, or event loop being "busy". An event loop is, essentially, this (in C++ pseudocode):
forever {
while (! nativeEventQueue.isEmpty()) {
QueueEntry entry = nativeEventQueue.take_first().convert();
QCoreApplication::sendEvent(entry.object, entry.event);
delete entry.event;
}
while (! eventQueue.isEmpty()) {
QueueEntry entry(eventQueue.take_first());
QCoreApplication::sendEvent(entry.object, entry.event);
delete entry.event;
}
waitFor(eventQueue, nativeEvents);
}
All of the event processing is done by sending some QEvent to a QObject. That's all that the event loop does. Some events result in the signals being emitted. It's not the event loop that is busy, it's the code that runs in the QObject::event and overridden implementations! This code blocks the event loop, since when it runs, the event loop's code is in the same thread and is on the call stack - it can't run.
Your code in slots connected to signals in Qt widgets and other objects is really executed while QCoreApplication::sendEvent and QCoreApplication::notify is on the call stack, with the event loop (a QAbstractEventDispatcher) somewhere deeper in the call stack, and finally a QEventLoop under it.
If your code executes at a pace that is slower than the events are added to the queue, you will have problems.
This trivial example demonstrates such code. In real programs it'll be of course "obfuscated", but the problem often reduces to:
void Class::customEvent(QEvent * ev) {
...
QCoreApplication::postEvent(this, new EventFoo(...));
...
QCoreApplication::postEvent(this, new EventFoo(...));
...
}
The explicit event posting can be expressed very differently. For example, it could be you sending a signal to yourself:
void Class::mySlot() {
...
emit signal1();
...
emit signal2();
}
If both signal1 and signal2 are connected to mySlot through a queued connection, your application will run out of memory, as the event queue will only grow, never shrink. It may still appear responsive.

How to guarantee signal delivery from multiple children

As part of a Linux benchmark application, I have a parent process that forks multiple children that will each perform a task in parallel. I'm using signals to coordinate between them since I'm looking for as accurate of timing as possible. Each child will prepare for the test, then enter a 'barrier' controlled by the parent via signals.
Once all the children have entered the barrier, the parent records the time stamp, and signals the child processes to begin. As soon as the child finishes each portion of the test they signal the parent before entering the next barrier. The parent is listening for these signals and once it receives them from all of the child processes, it records the completion time(s).
My problem is that the program terminates non-deterministically; the signals don't always get delivered. The signal handler could not be any simpler:
void sig_child_ready (int sig)
{
num_child_ready++;
}
num_child_ready is declared as volatile sig_atomic_t. I've tried using sigprocmask without success in a loop like this:
sigprocmask (SIG_BLOCK, &mask, &oldmask);
while (num_child_ready < num_child)
{
/* waiting for child signals here */
sigsuspend (&oldmask);
}
sigprocmask (SIG_UNBLOCK, &mask, NULL);
I'm not sure how to proceed from here. Am I correct that sigprocmask is needed to 'queue' the signals so they are processed one by one?
Or, consider this hypothetical scenario: the parent receives a signal, is executing its handler, then receives ANOTHER identical signal. Is the signal handler called recursively? ie will it execute the second handler before returning to, and completing the first handler?
I'm just looking to make sure all of the signals are delivered as synchronously as possible.
Normal signals are not queued, and that's likely the cause of your problem.
If one signal arrives before the handler has been run for a past signal, they'll get merged and there's little you can do about that - you're probably better off using some other form of IPC to do this kind of synchronization.
You could use "realtime signals", which do get queued. You'd send signals with sigqueue() and
"receive" them with sigwaitinfo() or establishing a signal handler setting the SA_SIGINFO flag in a struct sigaction