QtConcurrent::run and QList<QListWidgetItem*>::Iterator crashes



  • I'm on a small app, which fills a QListWidget with newed QListWidgetItems (around 40'000 items) while some of them are stored in a QList<QListWidgetItem*> (almost all of them). All are part of the same class: MainWidget.

    From there, I assumed that the QList pointers are exactely the same as some of the QListWidget's model. Stop me if I'm wrong.

    So based on that, when I click a button, a slot is executed (using QtConcurrent) to toggle the hidden attribute of all the QListWidgetItems contained in the QList<QListWidgetItem*>. Here is the code for toggle:

    void    MainWidget::toggle(void)
    {
        bool    newBool(!(*(this->m_okItems.cbegin() + 1))->isHidden());
    
        for (QList<QListWidgetItem*>::Iterator i(this->m_okItems.begin()); i != this->m_okItems.end(); ++i) {
            (*i)->setHidden(newBool);
        }
    
        this->endLoading();
    }
    

    And here is how I start the it

    QtConcurrent::run(this, &MainWidget::toggle);
    

    The first time I start this, it's OK. All the "hidden" items are shown, and vice-versa. The second time, it crashes during the execution of the QtConcurrent, and the debugger points to the asm instructions (I don't know ASM). I've also tried to put a qDebug() with a counter to see at which point it fails, if it's at the same item or not. It crashes randomly. Sometimes at the 35'000 th iteration, sometimes at 16'000th (rounded).

    I can't see how it could be related to thread safety as I disable the main GUI while the QtConcurrent is running (endLoading() is made to reenable to GUI). What am I missing?

    Thanks for your help.


  • Qt Champions 2016

    @Max13

    So based on that, when I click a button, a slot is executed (using QtConcurrent) to toggle the hidden attribute of all the QListWidgetItems contained in the QList<QListWidgetItem*>.

    This isn't allowed, so results are undefined (and undocumented).

    I can't see how it could be related to thread safety as I disable the main GUI while the QtConcurrent is running (endLoading() is made to reenable to GUI). What am I missing?

    You're missing the fact that QWidget and its descendants aren't reentrant.

    Kind regards.



  • @kshegunov Thanks for the hint. That's also why using a QMutex didn't change anything. So, please tell me how can I perform the heavy tasks in background on the list? Do I need to set the QList in another class and/or maybe the QListWidget model?


  • Qt Champions 2016

    @Max13
    Do whatever is you want to do with GUI in the main thread and call QCoreApplication::processEvents manually so you don't freeze up the user interface. Something like this:

    void MainWidget::toggle()
    {
        bool newBool = !m_okItems.at(1)->isHidden(); //< Just use C++, all the pointer dereferencing is making my head spin
    
        typedef QList<QListWidgetItem *>::ConstIterator ListIterator;
        for (ListIterator i = m_okItems.constBegin(); i != m_okItems.constEnd(); ++i)  {
            (*i)->setHidden(newBool);
            QCoreApplication::processEvents();
        }
    
        endLoading();
    }
    


  • @kshegunov Too bad :( I was afraid that was the only possible way... I tried that but it slowed down my app (maybe because each time I'm refreshing the whole widget for 1 add).

    I think I can get around the visual issue by creating a "Loading" widget with a progress bar and all that things in a thread instead. Then, I won't have to care much about the main GUI freezing, isn't it?



  • @kshegunov said:

    You're missing the fact that QWidget and its descendants aren't reentrant.

    Actually, I missed more than that... I completely miss the fact that, when dealing with QWidget or simillar + threads, that exactely when I should have used signal/slot mechanism... I feel dumb about it, but anyway, the Crawler object now crawls using Qt::Concurrent and send a signal with the text to add to the QListWidget, and then a MainWidget's slot is called to create and add the item.

    Thanks for your help


Log in to reply
 

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