2015-06-09 6 views
2

Я хочу, чтобы вызвать рекурсивную функцию-член, не класс, используемый для удаления заданной папки со всеми его файлами с использованием Qt 4.8 для встраиваемых Linux:Как вызвать функцию класса без класса с указателями в качестве параметров с помощью QtConcurrent :: run?

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-уловов, они были для «отладки ")

Как вы можете видеть, эта функция получает в качестве параметров как указатель на класс QProgressDialog, так и указатель на целое число. Класс QProgressDialog обновляет интерфейс с ходом операции удаления, а целое число хранит фактическое количество удаленных файлов.

Проблема у меня в том, что я постоянно получать ошибки сегментации, выравнивания ловушек и т.п., когда я называю эту функцию с помощью QtConcurrent :: Run:

concurrentResp = QtConcurrent::run(removeFiles, QString(DEFAULT_RECORD_DIR), poDialog, &itemCounter); 

То же самое не происходит, когда я звоню функция напрямую, поэтому я знаю, что это, вероятно, не проблема с функцией или с классом ProgressDialog. И у меня нет GDB, чтобы более тщательно отлаживать это (благодаря этому GDB с материалами Python).

Итак, мой вопрос в основном: что я делаю неправильно? И как мне это сделать без ошибок?

Дополнительно:

  • Как сейчас как ProgressDialog и целое являются глобальными в файле .cpp, но они были локальными некоторое время назад, и эта проблема уже существует.
  • Иногда ошибка сбоя появляется только при закрытии приложения в функции «возврат» в конце main(). Однако, как и сейчас, проблемы возникают даже до завершения четкой операции.

ответ

3

GUI может быть обновлен только с основного потока.

Вы пытаетесь обновить свое диалоговое окно из другого потока.

Попробуйте

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

вместо этого:

poProgressDialog->setValue(*itemDeletedCounter); 
+0

спасибо за отзыв, Murat, но ваше предложение не решило проблему сегментации (хотя это явное улучшение). – Momergil

+1

в конце концов, ваше решение будет правильным. Ошибка сегментации происходила из-за состояния гонки благодаря параметру 'Qt :: AutoConnection'. После изменения его на «Очередь» и использования регистратора мне удалось удалить некоторые операции «delete» и ненужные вызовы в 'QCoreApplication :: processEvents()', которые исправили segv. Благодаря! – Momergil

0

В общем, вы не должны изменять компонент пользовательского интерфейса непосредственно из фонового потока, это то, что вы делаете, когда вы звоните poProgressDialog->setValue(*itemDeletedCounter); из метода, который выполняется с QtConcurrent :: Run (...).

Существует учебное пособие here on how to use QtConcurrency with QProgressDialog. В основном это связано с использованием класса QFutureWatcher для мониторинга процесса поточно-безопасным способом с использованием сигналов и слотов.

1

Лучший подход заключается в создании соответствующего QObject для таких задач. Таким образом, большинство проблем бунтарей можно решить с помощью механизма слота сигнала. Также вы отделите интерфейс от фактической работы (что всегда рекомендуется).

Выполнение задачи, о которой вы должны сообщить, путем испускания сигналов, которые вы будете подключать к соответствующим слотам объектов пользовательского интерфейса.

+0

Спасибо за подсказку, Марек. Я действительно рассматривал этот подход раньше, но я хотел сделать функцию deleter неклассовой, поэтому я отбросил решение. – Momergil

 Смежные вопросы

  • Нет связанных вопросов^_^