На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела *nix / gcc / Eclipse / Qt / wxWidgets / GTK+
  • При создании темы ОБЯЗАТЕЛЬНО указывайте версию тулкита / библиотеки / компилятора.
  • Перед тем как задать вопрос, сформулируйте его правильно, чтобы вас могли понять.
  • Нарушение Правил может повлечь наказание со стороны модераторов.


Полезные ссылки:
user posted image Boost по-русски
user posted image Qt по-русски
Модераторы: archimed7592
  
> QProgressDialog , или как таки понять что я делаю не так
    День добрый. Собственно говоря такой вопрос:
    есть некий метод, получающий данные из одной БД некоторым образом обрабатывающий их и пишущий результат в другую БД (SQLite). Процесс этот достаточно длительный. Обрабатывается порядка 6 записей в секунду. При 20-30 тысячах записей длится достаточно долго. Дабы программа не производила впечатление зависшей решено добавить диалог прогресса с возможностью отмены. Ниже приведен код, выполняющий преобразование и
    [
    ExpandedWrap disabled
      bool UpdateDatabaseScript::unionDetailKPInfoTable()
      {
          QSqlQuery   query;
          /**
            *выбираем только те записи,
            * которые уже есть в  журнале
            */
          if(query.exec(QString("SELECT * FROM %1.Diagresult  WHERE ( %1.Diagresult.id  > %2  "
                                "AND %1.Diagresult.id <  %3 )" )
                        .arg(scriptName + "blob").arg(tempId).arg(lastId))){
       
              int i = 0;
              progressDialog->show();
              while (query.next()) {
                  ++i;
                  progressDialog->setValue(i);
                  qDebug() << progressDialog->value();
                  int id = query.record().value("id").toInt();
                  QArchblob tmpABLeft =  QArchblob(query.record()
                                                   .value("xmlResultBuksaLeft_pack").toByteArray());
                  tmpABLeft.UnPack();
                  QArchblob tmpABRight =  QArchblob(query.record().
                                                    value("xmlResultBuksaRight_pack").toByteArray());
                  tmpABRight.UnPack();
                  QString resXML = makeResultXML(tmpABLeft.toString(),
                                                 tmpABRight.toString(),id,this->guid);
                  insertIntoResultBlobtable(resXML,id,guid);
              }
              progressDialog->hide();
              return true;
          } else {
              return false;
          }
          return false;

    Вся беда в том, что значение в диалоге не обновляется во время выполнения. Он просто не перерисовывается. Хотя значения обновляются исправно. Очевидно, что дело не в бобине, но тем не менее хотелось бы понять что я делаю не так. Не хотелось бы выносить отрисовку в отдельный поток.
    Прикреплённая картинка
    Прикреплённая картинка
      Цитата kotmatroskin55 @
      Не хотелось бы выносить отрисовку в отдельный поток.

      Нелуччий выбор работы с GUI, да ланна ...

      Нехорошее решение

      В цикл обработки записей просто вставить вызов QCoreApplication::processEvents(флаги). На каждой итерации будет вызываться обработка событий приложения.

      Более хорошее решение

      Вызов QCoreApplication::processEvents(флаги) реализовать, скажем так, "адаптивным". Т.е. до входа в цикл обработки определяем преременную, например, bool LearnMode = true, а в коде разносим вызов в блок if, типа:

      ExpandedWrap disabled
        if (LearnMode) {
          // блок обучения
          } else {
          // блок исполнения
        }


      В "блоке обучения", вызывая таймеры, на первые M-итераций - находим такое приращение счетчика N, при котором N итераций выполняется за 0.3-0.4 секунды. Это определит чувствительность пользовательского интерфейса. Когда искомое N найдено меняем LearnMode=false и вызов QCoreApplication::processEvents будем осуществлять по условию if (i % N == 0) ... Естественно, если каждую итерациию можно определить за детерминированное время. В противном случае нужно применять "Нехорошее решение", а лучче вынести все же в отдельный поток и не мешать GUI делать свою работу.
        Цитата JoeUser @

        Нелуччий выбор работы с GUI, да ланна ...

        А поконкретнее можно, чего не так?
          Цитата kotmatroskin55 @
          А поконкретнее можно, чего не так?

          Главная задача основного потока в Qt - это работа с GUI. Если ты нагружаешь этот поток вычислениями любого толка, то получишь:
          1. В случае "Нехорошего решения" - приемлемый отклик пользовательского интерфейса и крайне низкую скорость вычислений
          2. В случае "Более хорошего решения" - большую (не максимальную) скорость вычислений и отклик пользовательского интерфейса с задержками, иногда вполне видимыми. Хотя они небольшие, но это неудобно.

          Резюме: GUI поток должен заниматься только GUI. Все вычисления нужно вынести в отдельный поток и ими управлять из GUI потока.
            Цитата JoeUser @
            Резюме: GUI поток должен заниматься только GUI. Все вычисления нужно вынести в отдельный поток и ими управлять из GUI потока.

            А как же правило: если есть возможность не использовать многопоточность, не используй. Или, ну как я понимаю, тут не тот случай?
            А решение, не спорю, не самое лучшее. Только времени на детальную проработку задачи нет. Сделать надо было еще вчера, а при этом качественно. Ну как обычно :)
              Цитата kotmatroskin55 @
              А как же правило: если есть возможность не использовать многопоточность, не используй.

              Так у тебя нет такой возможности, т.к. требуется асинхронность. Ну или подвешивай поток управления и отдавай ему "кванты" на обработку управляющих событий, как я описал выше.

              Цитата kotmatroskin55 @
              Только времени на детальную проработку задачи нет

              Используй первый подход тогда и не парься.
                Цитата JoeUser @

                Используй первый подход тогда и не парься.

                Так и сделал. С тормозами, но работает :) Спасибо.
                  Цитата kotmatroskin55 @
                  Цитата JoeUser @
                  Резюме: GUI поток должен заниматься только GUI. Все вычисления нужно вынести в отдельный поток и ими управлять из GUI потока.

                  А как же правило: если есть возможность не использовать многопоточность, не используй. Или, ну как я понимаю, тут не тот случай?
                  А решение, не спорю, не самое лучшее. Только времени на детальную проработку задачи нет. Сделать надо было еще вчера, а при этом качественно. Ну как обычно :)

                  Коммерческий код должен содержать хотя бы 8 потоков.
                    Цитата skrambun @
                    Коммерческий код должен содержать хотя бы 8 потоков.

                    Спорное утверждение которое необходимо доказать. К тому же какой эффект дадут эти 8 потоков, представим что они работают одновременно, на однопроцессорной машине? :blink:
                    1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                    0 пользователей:


                    Рейтинг@Mail.ru
                    [ Script execution time: 0,0760 ]   [ 16 queries used ]   [ Generated: 15.05.24, 06:43 GMT ]