QProgressDialog::setValue Crash



  • In MainWindow, I have the below code snippet.

    void MainWindow::Function_1()
    {
        /** some code here */
    
        int threadNum = 1000;///< just code snippet
        if(0 == _progressDlg){
            ///< _progressDlg MainWindow class data member.
            _progressDlg = new QProgressDialog(this);
            _progressDlg->setLabelText("Label text");
            _progressDlg->setRange(0,threadNum);
        }
    
        for(int i=0; i < subNum; i++){
            EngineTask* task = new EngineTask(...);///< 
            connect(task,&EngineTask::SigEngineTaskFinished,
                    this,&MainWindow::StEngineTaskFinished);
            _threadPool->start(task);
        }
    }
    

    I want to use the QProgressDialog to indicate the progress had done of my tasks.

    EngineTask class
    /** some include */
    
    class EngineTask : public QObject, public QRunnable
    {
        Q_OBJECT
    public:
        EngineTask(...);
        ~EngineTask();
    
        void run() override; ///< will emit SigEngineTaskFinished(...), in run function
    
    signals:
        void SigEngineTaskFinished(...);
    
    private:
        /** some class members */
    };
    
    
    MainWindow::StEngineTaskFinished

    In the slot, I update the value of QProgressDialog, But, some time, it can crashed at here.

    void MainWindow::StEngineTaskFinished(...)
    {
        /** some code here */
    
        if(0 != _progressDlg){
            int val = _progressDlg->value();
            val++;
            _progressDlg->setValue(); ///< ??? some time crash at here.
        }
    }
    

    I see the Qt help manual.

    Warning: If the progress dialog is modal (see QProgressDialog::QProgressDialog()), setValue() calls QApplication::processEvents(), so take care that this does not cause undesirable re-entrancy in your code. For example, don't use a QProgressDialog inside a paintEvent()!

    I don't clear it well now.

    1. How to work it out?
    2. what's best way?

  • Lifetime Qt Champion

    Hi,

    Any chance you forgot to initialise _progressDlg to 0 in your constructor ? Or you should rather use nullptr.



  • @SGaist

    I didn't forgot to initialise my class members.


  • Lifetime Qt Champion

    What does the stack trace tell you about the crash ?



  • @joeQ

    At the moment i do not know waht causes this crash.

    I tried many ways to work it out. not, i find one way.

    I test this way, not has the crash.

    my way

    In my mainwindow.h,

        /** MainWindow class data members */
        int              _progressVal   = 0;
        QTimer*          _progressTimer = 0;
        ProgressDialog*  _progressDlg   = 0;
    
        QThreadPool*     _threadPool    = 0;
    

    In MainWindow construct function

        /** some code */
    
        _progressTimer = new QTimer(this);
        _progressTimer->setInterval(1000);
        connect(_progressTimer,&QTimer::timeout,
                this,&MainWindow::StProgressTimerOut);
    
        /** some code */
    

    About the StProgressTimerOut

    void MainWindow::StProgressTimerOut()
    {
        if(0 == _progressDlg){
            _progressTimer->stop();
            return;
        }
    
        _progressDlg->setValue(_progressVal); ///< In here to update progressbar value
        if(_threadPool->activeThreadCount() == 0){
            _progressTimer->stop();
            _progressDlg->deleteLater();
            _progressDlg = 0;
            /** ... */
        }
    }
    

    So, When begin to start thread

        /** ... */
        int subNum = 100;
        for(int i=0; i < subNum; i++){
            task = new EngineTask(...);
            connect(task,&EngineTask::SigEngineTaskFinished,
                    this,&MainWindow::StEngineTaskFinished,Qt::QueuedConnection);
            _threadPool->start(task);
        }
    
        if(0 == _progressDlg){
            _progressDlg = new ProgressDialog(tr("Label text"),subNum,this);
            _progressTimer->start(500);
            _progressVal = 0;
        }
    

    In, the Slot function

        /**...*/
        _progressVal++;///< Not in slot to update progressbar value, update it in timer out slot function.
        /**...*/
    

  • Lifetime Qt Champion

    Why don't you create your dialog directly since you'll obviously use it ?
    That would avoid all these existence checks all over the place.

    Otherwise, it would also make more sense to create it before you generate your subNum tasks.



  • @SGaist yes, i will modify my code after. thank you very much.


Log in to reply
 

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