Russian Qt Forum
Ноябрь 23, 2024, 07:14 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Правильное разделение решателя и GUI (прогресса)  (Прочитано 6710 раз)
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« : Апрель 22, 2013, 09:45 »

Привет всем!!!
Небезизвестно, что если в одном потоке заключить какой-нибудь решатель и погресс диалог, то с прорисовкой графического интерфейса будут проблемы.
Меня интересует, как можно вывести в  отдельный поток решатель для нормального отображения прогресса с min(0), max(0) и возможностью отмены процесса решателя без внедрения в решатель каких-либо проверок (типа if(кнопка отмены была нажата) return;)
Записан
Bepec
Гость
« Ответ #1 : Апрель 22, 2013, 10:04 »

По делу -
1) выводим в поток, делаем сигналы с передачей процентов. Слоты GUI принимают и отображают прогрессбар.

2) никак. Тут тебе не вольное решение. Тут потоки. А потоки корректно завершить можно только двумя способами - флагом или концом внутреннего цикла событий.

PS погресс = прогресс.

PPS а "решатель" - это откуда у вас такой термин? (не ирония, действительно интересно)
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #2 : Апрель 22, 2013, 10:09 »

можно схалтурить и без потоков, вызывая периодически qApp->processEvents()
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #3 : Апрель 22, 2013, 11:55 »

Забыть про QThread и пользоваться QtConcurrent. Там даже пример есть для ProgressDialog с кнопкой Cancel.
Записан
Bepec
Гость
« Ответ #4 : Апрель 22, 2013, 12:00 »

А разница? там всёравно ж будут потоки, не?

PS и вроде ж конкурент для многопоточной обработки, а тут один "решатель".
Записан
Странник
Гость
« Ответ #5 : Апрель 22, 2013, 12:11 »

PPS а "решатель" - это откуда у вас такой термин? (не ирония, действительно интересно)
в определенных кругах термин используется по аналогии с английским solver.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #6 : Апрель 23, 2013, 08:31 »

А разница? там всёравно ж будут потоки, не?
Конечно, уровнем ниже там всё-равно потоки будут. Но от пользователя это будет скрыто. Да и для задачи автора темы оно прям идеально подходит.

PS и вроде ж конкурент для многопоточной обработки, а тут один "решатель".
В общем-то - да, это "высокоуровневое API для разработки многопоточных программ без использования низкоуровневых потоковых примитивов". Ну тут же уже как минимум 2 потока - "решатель" и "рисователь". Это пока ещё не очень много, но тут в перспективе и до многопоточного решателя без особых на то усилий добраться можно.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #7 : Апрель 23, 2013, 08:32 »

PPS а "решатель" - это откуда у вас такой термин? (не ирония, действительно интересно)
в определенных кругах термин используется по аналогии с английским solver.
В точку  Улыбающийся

На самом деле, я как-то не особо хорошо разобрался с QThread и у меня всё равно всё валит в одном потоке, да и нет сигнала finished(). Мне не нужно нормального завершения потока при нажатии на отмену.

Сейчас у меня есть класс, назовем его Parser. В нём есть слот parse. Есть ещё QThread* parserThread. Вот я moveToThread мой Parser* parser и connect(parserThread, SIGNAL(started()), parser, SLOT(parse())); connect(parserThread, SIGNAL(finished()), this, SLOT(showSuccessParse()));, где connect выдает везде значение true.
далее
Код:
parserThread->start();
parseProgrDlg->exec();
Результат: выполняется слот parse при этом показывается зависший диалог прогресса, а по завершении метода диалог отвисает и, по пока ещё не понятным мне причинам, не выполняется слот showSuccessParse()....
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #8 : Апрель 23, 2013, 08:35 »

Забыл добавить. Методом QtConcurent::run есть возможность решить данную проблему, но, при этом придётся делать флаг, на проверку которого не хотелось бы тратить время. По мне так лучше, убить поток... Не знаю, как правильно выразиться...
Записан
Bepec
Гость
« Ответ #9 : Апрель 23, 2013, 08:55 »

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

Это плохо Веселый Я и сам иногда так хочу, но потом вспоминаю и ай ай ай.

А то, что у вас зависает - значит у вас неправильно используется QThread. Больше кода - меньше слов и представлений.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #10 : Апрель 23, 2013, 12:02 »

Забыл добавить. Методом QtConcurent::run есть возможность решить данную проблему, но, при этом придётся делать флаг
Какой тут флаг и где?
Код
C++ (Qt)
void spin(int &iteration)
{
   const int work = 1000 * 1000 * 40;
   volatile int v = 0;
   for (int j = 0; j < work; ++j)
       ++v;
 
   qDebug() << "iteration" << iteration << "in thread" << QThread::currentThreadId();
}
 
...
 
// Create a QFutureWatcher and connect signals and slots.
   QFutureWatcher<void> futureWatcher;
   QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset()));
   QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
   QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int)));
   QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
 
   // Start the computation.
   futureWatcher.setFuture(QtConcurrent::map(vector, spin));
 
   // Display the dialog and start the event loop.
   dialog.exec();
 
   futureWatcher.waitForFinished();
 
   // Query the future to check if was canceled.
   qDebug() << "Canceled?" << futureWatcher.future().isCanceled();
}

По мне так лучше, убить поток... Не знаю, как правильно выразиться...
Не существует способа корректно "убить поток".
В любом случае кто-то  - или Вы, или QtConcurrent должен делать периодическую проверку флага между операциями, чтобы понять, что пользователь решил прервать операцию. Смиритесь с этим.
« Последнее редактирование: Апрель 23, 2013, 12:07 от xokc » Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #11 : Апрель 24, 2013, 10:07 »

В любом случае кто-то  - или Вы, или QtConcurrent должен делать периодическую проверку флага между операциями, чтобы понять, что пользователь решил прервать операцию. Смиритесь с этим.
Понял. Смирился. Спасибо.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.267 секунд. Запросов: 23.