QT : How to determine if the event processor is busy - c++

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.

Related

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.

How can I stop a long for loop when the widget (QDialog) running it is closed without multithreading?

I have a quite lengthy foreach loop in a QDialog. It basically looks like this:
foreach (xxx, xxx) {
... doSomeStuff ...
QApplication::processEvents();
if (m_cancelMapLoading) {
break;
}
}
m_cancelMapLoading is set to true by clicking a "Cancel" button. The QApplication::processEvents(); makes this possible.
This works quite fine, but if the dialog is closed as long as that foreach loop still runs, it continues running. I tried to set m_cancelMapLoading to true in each function closing the dialog, but this does not help.
I also tried to test not only for m_cancelMapLoading being true, but also for isVisible(). This actually stops the dialog, but it re-opens it at once without the GUI elements in it.
Unfortunately, QtConcurrent::run etc. can't be used for the function, because the data structures that are manipulated by the foreach loop are not thread safe.
Is there a convenient way to solve this?
You can use a QTimer and Qt's parent-child structure to your advantage here. QTimer with a timeout value of zero has a special meaning in Qt
As a special case, a QTimer with a timeout of 0 will time out as soon
as all the events in the window system's event queue have been
processed. This can be used to do heavy work while providing a snappy
user interface:
So you could do something like
void Dialog::beginDoingStuff()
{
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(processData());
m_timer->start(0);
}
void Dialog::processData()
{
// Perform one cycle of your process here
}
This will perform the processData() function in the same thread as the rest of the dialog, and when the dialog is destroyed by being closed, the timer will be deleted (because it's parent is the dialog), meaning the processing will stop.
A good and quite easy way to unload your GUI from heavy processing is assigning it to another thread or QtConcurrent.
You could then either poll a "should-I-terminate-yet?" variable or terminate the thread manually when it is no longer needed.
I highly recommend a parallel processing since offers better control rather than doing a "DoEvents"-like queue emptying.
We actually managed to solve the problem by connecting the dialog's finished signal to the click slot of the cancel button. This actually stops the loop in all circumstances.
We also introduced starting the function by a QTimer (for a nicer implementation not blocking the function where it's started), but this does not stop the loop (perhaps because we don't destroy the dialog when it's closed).
Thanks for all help :-)

How do I stop and start a loop in QT?

I've been trying to figure out how to make the program stop in a for-loop and wait for a button to be clicked and the for-loop continues.
Isn't there any easy way to stop the loop like QSystem.stop() and in the button clicked function QSystem.star() and the loop continues.
In C++ you could use system("pause") or the program stopped when you used a cin<<. But how do i do this in QT?
Since the userinterface needs its code to run, if you halt event loop (which also means that any function that gets called from within the event loop is blocking, waiting for some event), you also halt the user interface, which means clicks into the window won't be processed. That's why in event based programming, which is what all UI kits do, it is essential to return to the main event handler loop as quickly as possible.
What you can do is create a second thread and wait on a condition variable. The GUI thread can signal that condition variable in the button click event slot.
In C++ you could use system("pause") or the program stopped
Exactly: The program is stopped. Which means it won't fetch events from the operating system. However receiving data from stdin is not an event. It's blocking on streamed I/O. Graphical user interfaces are event based though.
Note that conceptually it's not really impossible to think of a user interface to provide streaming I/O channels. However that doesn't work in single threaded programs. You need parallel execution (coroutines, threads, or such) for a concept like this to work.
You don't need threads, nested event loop will do the job.
int waitUntilSignalIsEmitted(QObject *sender, const char *signal) {
QEventLoop loop;
connect(sender, signal,
&loop, SLOT(quit()));
return loop.exec();
}
// usage:
while(yourLoopCondition) {
// some stuff
...
// pause here
waitUntilSignalIsEmitted(yourContinuationButton, SIGNAL(clicked()));
// loop continuation
...
}

QThreads interruption with slots and signals

I have a class which contains QThread. In the initialization function of this class the thread should be started. This works correct. in the thread there I have a while(bool certainCondition){} this certainCondition should be changed by a signal/slot connection.
The problem is that during the while is running the signal/slot is not opened.
You are not running an event loop in your thread, or you are blocking for a long time in your while-loop. Your slot cannot be called until you have returned control to the event loop, which will happen after you have finished the while-loop.
As a workaround, you can try calling QCoreApplication::processEvents() inside your while-loop.
In order for signals/slots to work across threads, the event loop must run.
If you use a while loop, the event loop is never run, and hence signals are not received.
This is how you normally run the event loop:
void Thread::run()
{
...do something
exec(); //<<this runs the event loop
}
Now, your problem is that you want continuously run some code until some condition is met. In the above code, this won't work, because of the exec() call.
There are 2 possibilities to solve that (depending on what you want to achieve in your loop):
Use a QTimer, that fires let's say every 5 seconds, and calls a slot which executes your repeating code.
Use a QWaitCondition to check for a certain condition to be fulfilled; but then you cannot use signals and slots; instead you have to trigger the QWaitCondition.

How to put wait condition in Signal-Slot?

I am doing one web related project. Recently I hit on this situation. This is just a stub
Class My_Class
{
public:
My_Class();
void start();
public slots():
void after_Load_Function();
}
My_Class::My_Class()
{
//Some initializations
connect(WebPage,SIGNAL(finished()),this,SLOTS(after_Load_Function()));
}
void My_Class::start()
{
WebPage->load();
}
void My_Class::after_Load_Function()
{
//Do something with the finished WebPage
}
int main(int argc,char * argv[])
{
//Some Qt things
My_Class a;
a.start();
}
"WebPage" emits the signal "finished" when it loaded fully.
Now the problem is before the "webPage" got loaded the "start" is returning. Thereby the control reaches the "main". So, now the control should return from "start" only after "after_Load_Function" finishes it's job. Thereby I want the below sequence,
main creates the My_Class object A.
main calls "start" from A.
start calls load from "WebPage" and it waits untill the "WebPage" emits "finished",
and that emit in turn calls the "after_Load_Function", and "after_Load_Function"
finishes it's job.
now, the "start" returns
main returns
But, I don't know how to make this kind of wait condition. How can I go about it?
You can do this by running a local event loop, letting the components process network income and load the page. When they emit the signal, you execute a slot on the event loop to quit it.
void My_Class::start()
{
QEventLoop qel;
QObject::connect(WebPage, SIGNAL(finished()), &qel, SLOT(quit()));
WebPage->load();
qel.exec();
}
I've been using this before and it works fine. I don't advice to use this too often though, because it will process events, including those that the caller of start might not be expecting to be processed during the call to start, so you need to document this to its callers. You can prevent the processing of some events by passing certain flags to QEventLoop::exec, like preventing to process user interface events.
You should never wait in UI code. You need to break your "main" function into pieces so the later part can be executed separately.
Use condition variables thats what they are used for. You can make threads wait on a condition variable and proceed when notified.
The WebPage->load() method is asynchronous, meaning that it runs immediately, not when the loading is complete. The operation runs in the background while you go to do other things.
This is considered a good thing, as it enables your app to be more responsive and get more done. For example, if your app has a GUI, you could update the GUI with some sort of animation that indicates that the web page is being retrieved.
If you prefer a model in which the application blocks until the page is fully loaded, then consider making this change:
void My_Class::start()
{
WebPage->load();
while (!WebPage->isLoaded())
Sleep(1);
after_Load_Function();
}
Notes:
the Sleep function will work on Windows. If you are on a Unix OS you can use usleep.
since this function will effectively block until the web page is loaded, there is no reason to use the signal from the web page object, you can just simply call your handler after the wait completes, as this will make your handler run in the same thread.
doing this is really bad practice. You may get away with it if your program is command line and has no GUI and/or event loop, but you should consider a better design for your app where the loading of web pages does not block the whole app.