如何用QtConcurrent::run调用指针为参数的非class成员函数?

How to call a non-class member function with pointers as parameters with QtConcurrent::run?

我想使用 Qt 4.8 for Embedded 调用递归非 class 成员函数来擦除给定文件夹及其所有文件 Linux:

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

    try
    {
        QDir dir(dirName);

        if (dir.exists(dirName))
        {
            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);
                else
                {
                    result = QFile::remove(info.absoluteFilePath());

                    try
                    {
                        poProgressDialog->setValue(*itemDeletedCounter);
                    }
                    catch (...)
                    {
                        const QString strTemp = QString("Error in removeFiles::poProgressDialog->setValue(*itemDeletedCounter); !!!");

                        mDebugS(strTemp);
                        mLog(strTemp);
                    }

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

                if (!result)
                    return result;
            }

            result = dir.rmdir(dirName);
        }
    }
    catch (...)
    {
        const QString strTemp = QString("General error in removeFiles");

        mDebugS(strTemp);
        mLog(strTemp);
    }

    return result;
}

(忘记 try-catch;它们是为了 "debug")

如您所见,此函数接收一个指向类 QProgressDialog class 的指针和一个指向整数的指针作为参数。 QProgressDialog-like class 用删除操作的进度更新界面,整数存储实际删除的文件数。

我遇到的问题是,当我使用 QtConcurrent::run:

调用此函数时,我经常遇到分段错误、对齐陷阱等问题
concurrentResp = QtConcurrent::run(removeFiles, QString(DEFAULT_RECORD_DIR), poDialog, &itemCounter);

当我直接调用函数时不会发生同样的情况,所以我知道这可能不是函数或 ProgressDialog 的问题 class。而且我没有可访问的 GDB 来更仔细地调试它(感谢带有 Python 东西的 GDB)。

所以我的问题本质上是:我做错了什么?我应该怎么做才能不出错?

额外信息:

一般来说,您不应直接从后台线程修改 UI 组件,这就是您从使用 QtConcurrent::run 执行的方法调用 poProgressDialog->setValue(*itemDeletedCounter); 时所做的事情(...).

有教程here on how to use QtConcurrency with QProgressDialog。它基本上涉及使用 QFutureWatcher class 使用信号和槽以线程安全的方式监视进程。

GUI 只能从主线程更新。

您正在尝试从另一个线程更新您的对话框。

试试这个

QMetaObject::invokeMethod(poProgressDialog, "setValue",
                          Qt::AutoConnection,
                          Q_ARG(qint32, *itemDeletedCounter));

而不是这个:

poProgressDialog->setValue(*itemDeletedCounter);

最好的方法是为此类任务创建相应的 QObject。这样大部分的叛变问题都可以通过信号槽机制来解决。此外,您还将 UI 与实际工作分开(始终推荐)。

您应该通过发射信号来报告您的任务进度,您将连接到 UI 个对象的相应插槽。