My application is a windowing application that performs certain complex mathematical algorithms. Because I started with the application a long time ago, most of it is still single-threaded. To be more precise, the main thread executes all the complex calculation logic. It's important to mention that during the calculations, I show some progress on the screen.
In most cases, the mathematical algorithms only take several seconds, so after the user has started the action, an hourglass (or the running circle in Windows 7) is shown, and a few seconds later the results are shown.
In some cases, the algorithm can take several minutes. During this time, I show the hourglass, and while the algorithm is busy, I show the progress in my window. But, if the user clicks in the application after it has been busy for a while, the Window becomes 'more white' (as if a non-completely-transparent piece of plastic is laid over the window), the Window is not updated anymore, and Windows reports 'the application is not responding'.
I use Qt and I use the Qt function QWidget::repaint to force a repaint while my algorithm is busy. The repaint works for some time, but as said above, Windows seems to block this after a while.
What is the correct way to tell Windows that your application is still busy so that the window keeps on updating? If I enter an explicit message loop, the user might trigger other actions in the application which I don't want.
Notice that moving the calculation logic to a separate thread is currently not an option.
I'm using Visual Studio 2010 on Windows 7, in combination with Qt 4.7.
You should separate the GUI from the application logic. All other solutions are hacks. Moving the calculation logic to a separate thread can easily be achieved with Qt
using minor effort.
I assume that there is a function (lets call it execute()
) that when called performs all these time consuming mathematical operations. One option is to use the Qt Concurrent API for calling this function in a separate thread, without using low-level thread handling.
What you need is the QtConcurrent::run
function :
The QtConcurrent::run() function runs a function in a separate thread. The return value of the function is made available through the QFuture API.
Instead of simply calling execute()
which will block your User Interface you can do the following (let A
be the class in which execute()
is defined):
QFuture<void> future = QtConcurrent::run(this, &A::execute);
You can use QFutrureWatcher
in order to get notified about when the function has finished.
You could simply call QApplication::processEvents()
from time to time, say every 2 or 3 seconds or so. That should trigger a repaint event and refresh your progress bar and other elements.
Similar question and lots of info here: I need a message pump that doesn't mess up my open window
However, as you probably already know, this is quite a hack and it would be better to try to move the code to another thread. Why is this "not an option"?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With