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.
- How to work it out?
- what's best way?
-
Hi,
Any chance you forgot to initialise
_progressDlg
to 0 in your constructor ? Or you should rather usenullptr
. -
What does the stack trace tell you about the crash ?
-
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. /**...*/
-
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.