Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.117.85.200] |
|
Сообщ.
#1
,
|
|
|
День добрый. Собственно говоря такой вопрос:
есть некий метод, получающий данные из одной БД некоторым образом обрабатывающий их и пишущий результат в другую БД (SQLite). Процесс этот достаточно длительный. Обрабатывается порядка 6 записей в секунду. При 20-30 тысячах записей длится достаточно долго. Дабы программа не производила впечатление зависшей решено добавить диалог прогресса с возможностью отмены. Ниже приведен код, выполняющий преобразование и [ 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; Вся беда в том, что значение в диалоге не обновляется во время выполнения. Он просто не перерисовывается. Хотя значения обновляются исправно. Очевидно, что дело не в бобине, но тем не менее хотелось бы понять что я делаю не так. Не хотелось бы выносить отрисовку в отдельный поток. Прикреплённая картинка
|
Сообщ.
#2
,
|
|
|
Цитата kotmatroskin55 @ Не хотелось бы выносить отрисовку в отдельный поток. Нелуччий выбор работы с GUI, да ланна ... Нехорошее решение В цикл обработки записей просто вставить вызов QCoreApplication::processEvents(флаги). На каждой итерации будет вызываться обработка событий приложения. Более хорошее решение Вызов QCoreApplication::processEvents(флаги) реализовать, скажем так, "адаптивным". Т.е. до входа в цикл обработки определяем преременную, например, bool LearnMode = true, а в коде разносим вызов в блок if, типа: if (LearnMode) { // блок обучения } else { // блок исполнения } В "блоке обучения", вызывая таймеры, на первые M-итераций - находим такое приращение счетчика N, при котором N итераций выполняется за 0.3-0.4 секунды. Это определит чувствительность пользовательского интерфейса. Когда искомое N найдено меняем LearnMode=false и вызов QCoreApplication::processEvents будем осуществлять по условию if (i % N == 0) ... Естественно, если каждую итерациию можно определить за детерминированное время. В противном случае нужно применять "Нехорошее решение", а лучче вынести все же в отдельный поток и не мешать GUI делать свою работу. |
Сообщ.
#3
,
|
|
|
Цитата JoeUser @ Нелуччий выбор работы с GUI, да ланна ... А поконкретнее можно, чего не так? |
Сообщ.
#4
,
|
|
|
Цитата kotmatroskin55 @ А поконкретнее можно, чего не так? Главная задача основного потока в Qt - это работа с GUI. Если ты нагружаешь этот поток вычислениями любого толка, то получишь: Резюме: GUI поток должен заниматься только GUI. Все вычисления нужно вынести в отдельный поток и ими управлять из GUI потока. |
Сообщ.
#5
,
|
|
|
Цитата JoeUser @ Резюме: GUI поток должен заниматься только GUI. Все вычисления нужно вынести в отдельный поток и ими управлять из GUI потока. А как же правило: если есть возможность не использовать многопоточность, не используй. Или, ну как я понимаю, тут не тот случай? А решение, не спорю, не самое лучшее. Только времени на детальную проработку задачи нет. Сделать надо было еще вчера, а при этом качественно. Ну как обычно |
Сообщ.
#6
,
|
|
|
Цитата kotmatroskin55 @ А как же правило: если есть возможность не использовать многопоточность, не используй. Так у тебя нет такой возможности, т.к. требуется асинхронность. Ну или подвешивай поток управления и отдавай ему "кванты" на обработку управляющих событий, как я описал выше. Цитата kotmatroskin55 @ Только времени на детальную проработку задачи нет Используй первый подход тогда и не парься. |
Сообщ.
#7
,
|
|
|
Цитата JoeUser @ Используй первый подход тогда и не парься. Так и сделал. С тормозами, но работает Спасибо. |
Сообщ.
#8
,
|
|
|
Цитата kotmatroskin55 @ Цитата JoeUser @ Резюме: GUI поток должен заниматься только GUI. Все вычисления нужно вынести в отдельный поток и ими управлять из GUI потока. А как же правило: если есть возможность не использовать многопоточность, не используй. Или, ну как я понимаю, тут не тот случай? А решение, не спорю, не самое лучшее. Только времени на детальную проработку задачи нет. Сделать надо было еще вчера, а при этом качественно. Ну как обычно Коммерческий код должен содержать хотя бы 8 потоков. |
Сообщ.
#9
,
|
|
|
Цитата skrambun @ Коммерческий код должен содержать хотя бы 8 потоков. Спорное утверждение которое необходимо доказать. К тому же какой эффект дадут эти 8 потоков, представим что они работают одновременно, на однопроцессорной машине? |