QtConcurrent::run()
(Qt for Embedded Linux 4.8)によって呼び出される並列スレッドで、システムからファイルとフォルダーを削除する関数を呼び出したいと考えています。QFuture<bool>
withのみを使用しQFuture::waitForFinished()
て結果を取得し (操作の直後にコードを実行する必要があります)、システムを機能させることができました。
しかし、削除関数内からシグナルとスロットメカニズムを介しQProgressBar
て呼び出された派生クラスで操作の進行中の結果を表示したいのですが、上記の方法で得られるのは、操作が完了していない間にフリーズしたメインスレッドです。setValue(int)
そしてそれは認められません。
そのため、削除操作が完了した後に実行される残りのコードを含む別のスロットに信号を使用QFutureWatcher<bool>
して接続することについて考えました。finished()
私が直面している問題は、これを行うと、削除機能がQtConcurrent::run()
!によって実行されないことです。ターミナルに出力されたメッセージでそれを確認しました。発生するすべてのことは、ファイル削除機能を実行せずにQFutureWatcher
そのシグナルを呼び出すことです(これは、 を使用した場合にも発生します)。finished()
QFutureWatcher::waitForFinished()
これはQtのバグですか?
コードに関しては、Qt Assistant とまったく同じです。QFuture と QFutureWatcher をグローバルに作成し、finished() シグナルをスロットに接続し、 を呼び出してQtConcurrent::run()
、setFuture()
future に接続します。特にない。
どんな助けでも感謝します。
編集
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;
}