如何用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)。
所以我的问题本质上是:我做错了什么?我应该怎么做才能不出错?
额外信息:
- 至于现在ProgressDialog和integer在.cpp文件中都是全局的,但它们在一段时间之前是本地的,问题已经存在了。
- 有时段错误仅在main() 末尾的"return" 函数中关闭应用程序时出现。不过,现在的情况是,还没有完成清除操作就出现了问题。
一般来说,您不应直接从后台线程修改 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 个对象的相应插槽。
我想使用 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)。
所以我的问题本质上是:我做错了什么?我应该怎么做才能不出错?
额外信息:
- 至于现在ProgressDialog和integer在.cpp文件中都是全局的,但它们在一段时间之前是本地的,问题已经存在了。
- 有时段错误仅在main() 末尾的"return" 函数中关闭应用程序时出现。不过,现在的情况是,还没有完成清除操作就出现了问题。
一般来说,您不应直接从后台线程修改 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 个对象的相应插槽。