Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: __Heaven__ от Апрель 22, 2013, 09:45



Название: Правильное разделение решателя и GUI (прогресса)
Отправлено: __Heaven__ от Апрель 22, 2013, 09:45
Привет всем!!!
Небезизвестно, что если в одном потоке заключить какой-нибудь решатель и погресс диалог, то с прорисовкой графического интерфейса будут проблемы.
Меня интересует, как можно вывести в  отдельный поток решатель для нормального отображения прогресса с min(0), max(0) и возможностью отмены процесса решателя без внедрения в решатель каких-либо проверок (типа if(кнопка отмены была нажата) return;)


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: Bepec от Апрель 22, 2013, 10:04
По делу -
1) выводим в поток, делаем сигналы с передачей процентов. Слоты GUI принимают и отображают прогрессбар.

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

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

PPS а "решатель" - это откуда у вас такой термин? (не ирония, действительно интересно)


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: kambala от Апрель 22, 2013, 10:09
можно схалтурить и без потоков, вызывая периодически qApp->processEvents()


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: xokc от Апрель 22, 2013, 11:55
Забыть про QThread и пользоваться QtConcurrent. Там даже пример есть для ProgressDialog с кнопкой Cancel.


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: Bepec от Апрель 22, 2013, 12:00
А разница? там всёравно ж будут потоки, не?

PS и вроде ж конкурент для многопоточной обработки, а тут один "решатель".


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: Странник от Апрель 22, 2013, 12:11
PPS а "решатель" - это откуда у вас такой термин? (не ирония, действительно интересно)
в определенных кругах термин используется по аналогии с английским solver.


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: xokc от Апрель 23, 2013, 08:31
А разница? там всёравно ж будут потоки, не?
Конечно, уровнем ниже там всё-равно потоки будут. Но от пользователя это будет скрыто. Да и для задачи автора темы оно прям идеально подходит.

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


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: __Heaven__ от Апрель 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()....


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: __Heaven__ от Апрель 23, 2013, 08:35
Забыл добавить. Методом QtConcurent::run есть возможность решить данную проблему, но, при этом придётся делать флаг, на проверку которого не хотелось бы тратить время. По мне так лучше, убить поток... Не знаю, как правильно выразиться...


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: Bepec от Апрель 23, 2013, 08:55
Проще выражаясь вы, как и любой начинающий работать с потоками, хотите его убивать и возрождать мгновенно без проверки флагов.

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

А то, что у вас зависает - значит у вас неправильно используется QThread. Больше кода - меньше слов и представлений.


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: xokc от Апрель 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 должен делать периодическую проверку флага между операциями, чтобы понять, что пользователь решил прервать операцию. Смиритесь с этим.


Название: Re: Правильное разделение решателя и GUI (прогресса)
Отправлено: __Heaven__ от Апрель 24, 2013, 10:07
В любом случае кто-то  - или Вы, или QtConcurrent должен делать периодическую проверку флага между операциями, чтобы понять, что пользователь решил прервать операцию. Смиритесь с этим.
Понял. Смирился. Спасибо.