1

QtConcurrent::run()我想在(Qt for Embedded Linux 4.8)调用的并行线程中调用一个函数来从系统中删除文件和文件夹。仅使用QFuture<bool>withQFuture::waitForFinished()来获取结果(我需要在操作后立即运行一些代码),我能够使系统工作。

但是我想在QProgressBar派生类中显示操作的正在进行的结果,setValue(int)并从删除函数内部通过信号和槽机制调用它,而我用上述方法得到的是一个冻结的主线程,而操作还没有完成,这是不可接受的。

所以我想使用QFutureWatcher<bool>它的finished()信号并将其连接到另一个插槽,其中包含要在删除操作完成后运行的剩余代码。

我面临的问题是,当我这样做时,删除功能根本不是由QtConcurrent::run()!我通过打印到终端的消息检查了这一点。发生的一切都是在没有执行任何删除文件功能的情况下QFutureWatcher调用其finished()信号(如果我使用,也会发生这种情况QFutureWatcher::waitForFinished())。

这是Qt的一些错误吗?

关于代码,它与 Qt Assistant 中的完全一样:全局创建 QFuture 和 QFutureWatcher,将 finished() 信号与 slot、callQtConcurrent::run()setFuture()未来连接。没什么特别的。

任何帮助表示赞赏。

编辑

按照 Kuba 的要求,这里是代码的相关部分:

//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;
}
4

0 回答 0