Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Общие вопросы _ processEvents() & quit()

Автор: igor_bogomolov 18.5.2009, 11:59

Привет всем.
Столкнулся с проблемкой, что-то не пойму как решить.

При старте программы, в основном потоке вызывается длительная функция ~40c (она прогружает платы с ADSP). В силу некоторых причин, не хотелось бы выносить ее в дополнительный поток. Для того чтобы Gui не блокировался, периодически вызывается qApp->processEvents().

void ThreadScan::exeLoader(const QString& modules, const QString& loadFile) {
    forever {
        .....
        qApp->processEvents();
    }
}
Есть QAction связанный с QCoreApplication::quit ()
connect(actionExit, SIGNAL(triggered()), qApp, SLOT(quit()));
Так вот, если в процессе выполнения exeLoader высылается quit, программа не завершается, как мне хотелось бы. Завершится только тогда, когда выйдет из exeLoader.

Возможно ли это обойти, не вынося функцию в доп. поток?

Автор: kwisp 18.5.2009, 12:38

igor_bogomolov,
в каком случае вызывается exeLoader ???
в каком месте программы она вызывается, случаем не до входа в основной цикл обработки событий?


Цитата(igor_bogomolov @ 18.5.2009, 12:59) *
высылается quit,

вот это еще не понятно, высылается вроде бы triggered
т.е. соединение срабатывает во время а программа закрывается только после завершения функции exeLoader

так???

Автор: igor_bogomolov 18.5.2009, 12:59

Цитата(kwisp @ 18.5.2009, 13:32) *
в каком месте программы она вызывается, случаем не до входа в основной цикл обработки событий?
нет, конечно. Цикл обработки событий в момент вызова запущен. Другие события обрабатываеются. Не обрабатывается только выход из программы. В асистенте есть замечание по этому поводу. Можно ли это обойти?

Цитата(kwisp @ 18.5.2009, 13:38) *
вот это еще не понятно, высылается вроде бы triggered
т.е. соединение срабатывает во время а программа закрывается только после завершения функции exeLoader
Ты все правильно понял. Это я просто так сформулировал.

К примеру, есть два коннекта. aboutQt() отробатывает в процессе выполнения exeLoader, quit() - нет.
    connect(actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
    connect(actionExit, SIGNAL(triggered()), qApp, SLOT(quit()));


В книге Бланшета есть такой абзац
Цитата
One danger with this approach is that the user might close the main window while the application is still saving, or even click File|Save a second time, resulting in undefined behavior. The easiest solution to this problem is to replace
qApp->processEvents();
with
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
Мне же, как раз таки и надо закрыть окно во время выполнения, но этого не происходит.

Автор: kwisp 18.5.2009, 13:19

а
void QCoreApplication::exit ( int returnCode = 0 )
не пробовал?

если processEvents вызывается не каждую итерацию цикла то можно с помощью еще одной проверки было ли или нет событие закрытия выходить из цикла и соответтсвенно закрывать программу

что то типа

connect(actionExit, SIGNAL(triggered()), qApp, SLOT(quit()));
connect(actionExit, SIGNAL(triggered()), this, SLOT(setCloseMeTrue()));
.....
void ThreadScan::exeLoader(const QString& modules, const QString& loadFile) {
    forever {
        .....
        qApp->processEvents();
        if(closeMe) return 0;
    }
}

думаю если грузишь 40с много времени одна проверка не оттяпает. хотя конечно способ кривенький, признаю.:)

Автор: igor_bogomolov 18.5.2009, 13:32

Попробовал. Тоже самое, к сожалению. :(
Приложение завершается при выходе из exeLoader, а не в процессе выполнения.

-------------
Видимо стандартными методами Qt не получится. Придется свои флаги выставлять.

Автор: SABROG 18.5.2009, 13:59

Если так попробовать?

QMetaObject::invokeMethod(qApp, "quit", Qt::DirectConnection);

Автор: kwisp 18.5.2009, 14:06

SABROG,
ставлю 1р на то что не получится ибо было бы несправедливо по отношению к exit(0);

Автор: SABROG 18.5.2009, 14:11

Цитата(kwisp @ 18.5.2009, 15:06) *
SABROG,
ставлю 1р на то что не получится ибо было бы несправедливо по отношению к exit(0);

Скорее всего ты прав. На сколько я помню слот quit() ставит в очередь event, который может обрабатываться позже.

Тогда стандартную ::exit(0) пробовать, хотя мне кажется это некорректным.

А вообще не понятно. Предположим юзер нажал на крестик, обработался слот closeEvent. В этом слоте выставляем флаг типа "все, Вась! Вылазим." Этот флаг проверяется в цикле forever(), из которого выходим по return или по break. Ну и все, фенита ля комедия.

Автор: igor_bogomolov 18.5.2009, 14:17

Цитата(SABROG @ 18.5.2009, 14:59) *
QMetaObject::invokeMethod(qApp, "quit", Qt::DirectConnection);
Не помогло. То же самое поведение, что и раньше.

Ладно, спасибо всем за помощь. Буду выставлять флаг, по которому моя функция будет завершаться.

Автор: kwisp 18.5.2009, 14:19

Цитата(SABROG @ 18.5.2009, 15:11) *
Тогда стандартную ::exit(0) пробовать, хотя мне кажется это некорректным.


если кроме флага и стандартного exit() нет ничего почему бы не воспользоваться.

Автор: igor_bogomolov 18.5.2009, 14:25

Цитата(SABROG @ 18.5.2009, 15:11) *
А вообще не понятно. Предположим юзер нажал на крестик, обработался слот closeEvent. В этом слоте выставляем флаг типа "все, Вась! Вылазим." Этот флаг проверяется в цикле forever(), из которого выходим по return или по break. Ну и все, фенита ля комедия.
Так и собираюсь сделать. Только не через событие closeEvent (оно у меня и так переопределено. По нему приложение в трей сварачивается), а через свой слот.

Только абзац из Бланшет теперь уж больно смущает. Да и почему такое поведение троли заложили, для безопасности чтоли?

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)