PDA

View Full Version : Allowing external events to fire during a tight loop



hardgeus
27th December 2006, 15:51
In my application I have run into a situation (SFTP downloading) where I need to repeatedly loop for quite a bit of time inside of an event. As of right now, my whole app is frozen during the download, which is of course not desirable.

My first instinct is to use a QThread for the download, but that would require a fair amount of re-coding of the existing app. Is there a way I could hand back control to the app's event pump during my loop? I was thinking of something like this:



//Called from my button click slot
int DownloadFile() {
if( m_Semaphore ) {
return(0);
}
m_Semaphore = 1; //To keep this function from being called again during download
int bytesleft = checkfilesize();
while( bytesleft ) {
bytesleft -= downloadsomedata();
//Is there something I could call like this that allows app
//Event loop to continue?
::AllowMessagePumpToRun();
}

m_Semaphore = 0;
} //DownloadFile


I know this isn't the world's most desirable solution, but I was hoping that I could accomplish this without a major rewrite of this code. The SFTP overhead I have in my class is somewhat bulky, and I doin't want to have to move all of this over into a new class. (I know, it was a bad idea to tie all of this functionality into my Window class)

jpn
27th December 2006, 15:55
See QCoreApplication::processEvents().

hardgeus
27th December 2006, 17:18
See QCoreApplication::processEvents().

This works great, but now if the user clicks the "x" button in the top right to shut down the program, the download just continues in the background until it is complete. I already have a boolean that can cancel the download, and I have a CancelDownload slot attached to a Cancel button, which works fine. I tried connecting this slot to the destroyed() signal of the Window to let the loop know it's time to quit, but that event is never fired. I connected to the aboutToQuit() signal of QCoreApplication, which is getting fired under normal circumstances (debug() shows that the signal is firing), but this signal never gets fired as long as I'm in my tight loop.

jpn
27th December 2006, 17:34
I tried connecting this slot to the destroyed() signal of the Window to let the loop know it's time to quit, but that event is never fired.
This is because the window is not deleted when it's closed. You can get it deleted upon close by setting attribute Qt::WA_DeleteOnClose. See QWidget::setAttribute().

hardgeus
27th December 2006, 18:13
This is because the window is not deleted when it's closed. You can get it deleted upon close by setting attribute Qt::WA_DeleteOnClose. See QWidget::setAttribute().

I set that, and I'm pretty sure that it is now being deleted, because I got segfaults on close until I realized I had to change to dynamic allocation of my window after setting DeleteOnClose. Still no dice, my slot gets called when the program closed during idle, but it isn't getting called inside of the loop.

jpn
28th December 2006, 11:32
What if you override QWidget::closeEvent() and set the flag there? The event handler should get called at least.

hardgeus
28th December 2006, 15:24
What if you override QWidget::closeEvent() and set the flag there? The event handler should get called at least.

That works and the upload stops! Praise the gods. For a minute, I was getting a segfault, but it turns out I was popping up a messagebox on cancel which was crashing. Thanks for all of your help!