Slot called multiple times to a blocking function in the same thread
-
@joeQ The slot being called multiple time is not accidental ; it just happens for example if I push a button 2 times.
The code is here : Github
addWhateverToList is the slot being called and FilesEncrypt::getFilesFromDirRecursive is the function that takes time.
@jsulm I used QApplication::processEvents() just to test what happens if my function becames "non-blocking".
-
The correct way to proceed, as mentioned by @jsulm is to move the heavy lifting to a separate thread but,
This is a hack!
You can put a queue slot in between:
private: Q_SLOT void lenghtyOp(){ lenghtyOpQueued =false; // do the slow stuff } bool lenghtyOpQueued = false; public: Q_SLOT void queueLenghty(){ if(lenghtyOpQueued) return; lenghtyOpQueued =true; QTimer::singleShot(100,this,SLOT(lenghtyOp())); }
now connect your button to
queueLenghty
rather than tolenghtyOp
also, you probably want to add an argument to
processEvents
:QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
-
@VRonin said in Slot called multiple times to a blocking function in the same thread:
You can put a queue slot in between:
private: Q_SLOT void lenghtyOp(){ lenghtyOpQueued =false; // do the slow stuff } bool lenghtyOpQueued = false; public: Q_SLOT void queueLenghty(){ if(lenghtyOpQueued) return; lenghtyOpQueued =true; QTimer::singleShot(100,this,SLOT(lenghtyOp())); }
I prefered to use QtConcurrent::run it's much cleaner but thanks for the trick !
Thank you all for your answers :)
-
@moffa13 said in Slot called multiple times to a blocking function in the same thread:
QtConcurrent::run it's much cleaner
I don't want to be that guy, but I'd bet my left eye you are doing multi-threading wrong here. Are you sure you don't have a race-condition on
ui->tableWidget
if you use that? -
@VRonin said in Slot called multiple times to a blocking function in the same thread:
@moffa13 said in Slot called multiple times to a blocking function in the same thread:
QtConcurrent::run it's much cleaner
I don't want to be that guy, but I'd bet my left eye you are doing multi-threading wrong here. Are you sure you don't have a race-condition on
ui->tableWidget
if you use that?I don't understand why would I have this ?
Here's my final code : linkMy lambda function is not doing anything to ui->tableWidget
-
@moffa13 said in Slot called multiple times to a blocking function in the same thread:
my thread is changing is a QTableWidgetItem which cannot be changed by something else
if the QTableWidgetItem is visible in a view then the view will directly call the item for read every repaint, hence race condition
-
@VRonin said in Slot called multiple times to a blocking function in the same thread:
@moffa13 said in Slot called multiple times to a blocking function in the same thread:
my thread is changing is a QTableWidgetItem which cannot be changed by something else
if the QTableWidgetItem is visible in a view then the view will directly call the item for read every repaint, hence race condition
Actually I said something wrong. The part who is modifying the QTableWidgetItem is the QFutureWatcher<>::finished slot, which is accessed by the main thread, I think.
One question : Is it bad to lock and unlock a mutex multiple times ?For example :
_mutex.lock(); //Some var to be protected _mutex.unlock(); //Thread-safe heavy function _mutex.lock(); //Some var to be protected _mutex.unlock();
Thanks !