Slot called multiple times to a blocking function in the same thread



  • Hello,

    I was wondering what would happen if a widget in my gui was calling the same slot multiple times, so everything is happening in the same thread.

    The slot is a blocking function which takes lot of time to end.

    I saw that it was able to handle the signals emitting to the same slot (for example clicking a button) if there was a QApplication::processEvents(); somewhere in the slot

    Would'nt it cause memory problems if the function is called again but the first call isn't finished yet ?

    Thanks for help !



  • @moffa13 Hi, friend welcome.

    About what you said, the same slot multiple times, maybe you wrote some code to emit the signal(value changed signal, state changed signal ...).
    some time, we called the qt inner function, these function maybe changed some value and emit some signal. like QListWidget::currentRowChanged(int currentRow) signal

    1. user can clicked item to emit this signal;
    2. i also can setCurrentRow(row) in my program to emit this signal.

    i called this slot signal loop; like below code snippet;

    connect(listWidget,&QListWidget::currentRowChanged,this,&Class::RowChanged);
    
    void Class::RowChanged(int row)
    {
        /** it is best to disconnect begin of slot fuction */
        disconnect(listWidget,&QListWidget::currentRowChanged,this,&Class::RowChanged);
    
        /** maybe at here i use setCurrent() function to changed the current row ,and will emit row changed signal again */
    
        connect(listWidget,&QListWidget::currentRowChanged,this,&Class::RowChanged);
    }
    

    If I guessed wrong. Can you show some code snippet for here? it will help us to understand your problem well.


  • Moderators

    @moffa13 said in Slot called multiple times to a blocking function in the same thread:

    Would'nt it cause memory problems if the function is called again but the first call isn't finished yet ?

    Memory problems? Usually not. But you could have other issues if the slot you're calling isn't re-entrant. For example if you have a static variable inside the slot.
    But in general you should avoid blocking slots and QApplication::processEvents() is nothing more than an ugly work around and a sign of bad design. Move long lasting operations to other threads.



  • @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 to lenghtyOp

    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 : link

    My lambda function is not doing anything to ui->tableWidget



  • I have to be honest, I did not dig deep in to your code, but at first glance it looks like I lost my left eye in the bet πŸ˜‰



  • Well, I think there is no problem here because the only thing my thread is changing is a QTableWidgetItem which cannot be changed by something else by the logic of my code.



  • @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 !



  • @moffa13 said in Slot called multiple times to a blocking function in the same thread:

    One question : Is it bad to lock and unlock a mutex multiple times ?

    No, that's exactly what they are deigned for


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.