我想调用一个函数来从QtConcurrent::run()
调用的并行线程中删除系统中的文件和文件夹(Qt for Embedded Linux 4.8)。仅使用QFuture<bool>
和QFuture::waitForFinished()
来获取结果(我需要在操作后立即运行一些代码),我才能使系统正常工作。
但是我想在QProgressBar
派生类中显示正在进行的操作结果,其中setValue(int)
通过删除函数内部的信号和插槽机制调用,以及我用上面的方法获得的内容操作未完成时是一个冻结的主线程,这是不允许的。
所以我虽然使用QFutureWatcher<bool>
并将其finished()
信号连接到另一个包含剩余代码的插槽,该代码将在删除操作完成后运行。
我面临的问题是,当我这样做时,删除功能根本不是由QtConcurrent::run()
运行的!我检查了打印消息到终端。发生的一切都是QFutureWatcher
调用其finished()
信号而不执行删除文件功能(如果我使用QFutureWatcher::waitForFinished()
也会发生这种情况)。
这是Qt的一些错误吗?
关于代码,它与Qt Assistant完全一样:全局创建QFuture和QFutureWatcher,将finished()信号与插槽连接,将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;
}