Функция не работает с QtConcurrent::run() при использовании QFutureWatcher

Я хочу вызвать функцию для удаления файлов и папок из системы в параллельном потоке, вызываемом QtConcurrent::run() (Qt для встраиваемых Linux-систем 4.8). Используя только QFuture<bool> с QFuture::waitForFinished() чтобы получить результат (мне нужно запустить код сразу после операции), я смог заставить систему работать.

Но я хочу отобразить текущий результат операции в QProgressBar производный класс с его setValue(int) вызывается с помощью механизма сигналов и слотов внутри функции удаления, и то, что я получаю с помощью вышеупомянутого метода, является замороженным основным потоком, пока операция не завершена, и это недопустимо.

Так что я думал об использовании QFutureWatcher<bool> и подключение это finished() подайте сигнал в другой слот, содержащий оставшийся код, который будет запущен после завершения операции удаления.

Проблема, с которой я сталкиваюсь, заключается в том, что когда я делаю это, функция удаления просто не запускается QtConcurrent::run()! Я проверил это с помощью печатных сообщений в терминал. Все, что происходит, это то, что QFutureWatcher называет его finished() сигнал без какого-либо выполнения функции удаления файлов (и это также происходит, если я использую QFutureWatcher::waitForFinished()).

Это какая-то ошибка в Qt?

Что касается кода, он в точности такой же, как в Qt Assistant: создайте QFuture и QFutureWatcher глобально, соедините сигнал Finish () со слотом, вызовите QtConcurrent::run(), а также setFuture() в будущем. Ничего особенного.

Любая помощь приветствуется.

РЕДАКТИРОВАТЬ

Следуя просьбе Кубы, вот соответствующая часть кода:

//Declared globally in the .cpp
QFuture<bool> future;
QFutureWatcher<bool> watcher;

//
void SelectRecordToDeleteWidget::slotDeleteRecordStateMachine()
{
    switch (deleteRecordStateMachine)
    {
        case PrepareToDelete:
        {
            //...
            connect(&watcher,SIGNAL(finished()),this,SLOT(slotDeleteRecordStateMachine()),Qt::UniqueConnection);
            //...
        }
            break;

        case DeleteRecords:
        {
            //...
            future = QtConcurrent::run(removeFiles, QString(DEFAULT_RECORD_DIR) + "/" + recordList.at(aaa).second.second, poProgressDialog, &itemCounter);

            watcher.setFuture(future);

            qApp->processEvents();
            //...
        }
            break;

        case FinishDelete:
        {
            //Run code after deleting files
        }
            break;

        default:
            break;
    }
}

Это весь код, использующий QFuture и QFutureWatcher. removeFiles выглядит следующим образом (не забывая, что он хорошо работает без QFutureWatcher):

bool removeFiles(const QString dirName, Interface::ProgressDialog* const poProgressDialog, qint32* const itemDeletedCounter)
{
    bool result = true;

    try
    {
        QDir dir(dirName);

        if (dir.exists())
        {
            Q_FOREACH (QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
            {
    //            if (Q_UNLIKELY(poProgressDialog->wasCanceled()))
    //                break;

                if (info.isDir())
                {
                    result = removeFiles(info.absoluteFilePath(),poProgressDialog,itemDeletedCounter);

                    if (!result)
                        return result;
                }
                else
                {
                    result = QFile::remove(info.absoluteFilePath());

                    if (!result)
                        return result;

                    if (!QMetaObject::invokeMethod(poProgressDialog, "setValue",
                                              Qt::BlockingQueuedConnection,
                                              Q_ARG(qint32, *itemDeletedCounter)))
                    {
                        mDebugS(QString("removeFiles: %1QMetaObject::invokeMethod(poProgressDialog, \"setValue\"... failed!"));
                    }

                    ++(*itemDeletedCounter);

//                    mDebugS(QString("removeFiles: %1").arg(*itemDeletedCounter));
                }
            }

            result = dir.rmdir(dirName);
        }
    }
    catch (...)
    {
        const QString strTemp = QString("An error in a call to removeFiles");

        mDebugS(strTemp);
        mLog(strTemp);
    }

    return result;
}

0 ответов

Другие вопросы по тегам