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