QtConcurrent::map аварийно завершает работу, если не отображается QProgressDialog

Рассмотрим этот SLOT в моем основном потоке, вызванный кнопкой, которая берет список QTreeWidgetItem из QTreeWidget. Он использует вызов QtConcurrent::map() для выполнения длинной задачи. watcher подключается к QProgressDialog, чтобы показать прогресс.

void Main::on_actionButton_triggered() {
    qRegisterMetaType<QVector<int> >("QVector<int>");

    //Setting up a progress dialog
    QProgressDialog progressDialog;

    //Holds the list
    QList<QTreeWidgetItem*> list;

    //Setup watcher
    QFutureWatcher<void> watcher;

    //Setting up connections
    //Progress dialog
    connect(&watcher, SIGNAL(progressValueChanged(int)), &progressDialog, SLOT(setValue(int)));
    connect(&watcher, SIGNAL(progressRangeChanged(int, int)), &progressDialog, SLOT(setRange(int,int)));
    connect(&watcher, SIGNAL(progressValueChanged(int)), ui->progressBar, SLOT(setValue(int)));
    connect(&watcher, SIGNAL(progressRangeChanged(int, int)), ui->progressBar, SLOT(setRange(int,int)));
    connect(&watcher, SIGNAL(finished()), &progressDialog, SLOT(reset()));
    connect(&progressDialog, SIGNAL(canceled()), &watcher, SLOT(cancel()));

    connect(&watcher, SIGNAL(started()), this, SLOT(processStarted()));
    connect(&watcher, SIGNAL(finished()), this, SLOT(processFinished()));

    //Gets the list filled
    for (int i = 0; i < ui->listTreeWidget->topLevelItemCount(); i++) {
        list.append(ui->listTreeWidget->topLevelItem(i));
    }

    //And start
    watcher.setFuture(QtConcurrent::map(list, processRoutine));

    //Show the dialog
    progressDialog.exec();

}

extern void processRoutine(QTreeWidgetItem* item) {
    qDebug() << item->text(4);
}

Я также добавил в пользовательский интерфейс (который содержит все предыдущие виджеты) QProgressBar с теми же СИГНАЛАМИ/СЛОТАМИ. Сохранение кода, подобного предыдущему, работает так, как ожидалось: отображается диалоговое окно прогресса, и индикатор выполнения обновляется точно так же, как и диалоговое окно. Вместо этого, если я прокомментирую

//progressDialog.exec(); 

или я каким-то образом скрываю диалог, процесс вылетает (не всегда, иногда проходит нормально). Глядя на qDebug() << item->text(4);, он вылетает, и на выходе отображается случайно смешанный текст (предполагается, что это имена файлов). Кроме того, индикатор выполнения не обновляется, когда QProgressDialog не отображается, даже если вычисление не завершается сбоем.

Примечание. Ранее у меня возникала аналогичная проблема в другой функции, и я решил ее, установив

QThreadPool::globalInstance()->setMaxThreadCount(1);

только в Windows, OSX был в порядке.

Итак, в чем секрет QProgressDialog, который делает все правильно? Есть ли способ использовать QProgressBar вместо QProgressDialog?

ПРИМЕЧАНИЕ

Это вывод, когда процесс завершается без проблем:

"C:/Users/Utente/Pictures/Originals/unsplash_52cee67a5c618_1.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1428278953961-a8bc45e05f72.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1429152937938-07b5f2828cdd.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1429277158984-614d155e0017.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1430598825529-927d770c194f.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1433838552652-f9a46b332c40.jpg"

person Lymphatus    schedule 19.08.2015    source источник


Ответы (1)


Когда вы комментируете progressDialog.exec();, ваша функция on_actionButton_triggered() завершается уничтожением progressDialog, поэтому ваши сигналы используют указатели в никуда. Также watcher также уничтожается до или после выполнения всего сопоставления, и на самом деле это не останавливает потоки, поэтому они также работают в никуда.

person Jerry    schedule 24.08.2015