Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: thechicho от Ноябрь 25, 2011, 17:09



Название: правильно грохнуть поток
Отправлено: thechicho от Ноябрь 25, 2011, 17:09
для удаления после выполнения run()
Код
C++ (Qt)
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
для удаления после нажатия на кнопку
Код
C++ (Qt)
connect(ui->pushButtonStart, SIGNAL(clicked()), thread, SLOT(terminate()));
в release-версии это работает.
в debug прога жестоко зависает, после нажатия на кнопку.
в Qt Creator в Application Output постится ошибка:
QSocketNotifier: socket notifiers cannot be disabled from another thread
Qt Creator даже подвисает. ради интереса глянул сколько строк запостилось до краха проги - 74к!!!  :o
wtf? >:(
почему так? ???
как правильно надо делать? :-\


Название: Re: правильно грохнуть поток
Отправлено: BRE от Ноябрь 25, 2011, 17:14
Нельзя правильно грохнуть поток, правильно это когда поток останавливается сам.


Название: Re: правильно грохнуть поток
Отправлено: thechicho от Ноябрь 25, 2011, 17:28
я не догнал намека.
мне надо, чтобы после нажатия на кнопку поток сразу сдох
как это правильно делается? :-\


Название: Re: правильно грохнуть поток
Отправлено: thechicho от Ноябрь 25, 2011, 17:29
ну или не сразу. а чтобы выполнение прекратилось, т.е. чтобы не нужно было ждать пока run() до конца выполнится.


Название: Re: правильно грохнуть поток
Отправлено: BRE от Ноябрь 25, 2011, 17:31
Выставить флажок, поток его проверит и завершиться.
Не используй terminate, это жесткое убийство потока, которое может произойти в самый неподходящий момент. Не жди что это будет безболезненно. ;)


Название: Re: правильно грохнуть поток
Отправлено: thechicho от Ноябрь 25, 2011, 17:37
в цикле while (flag) ?
не вижу в этом смысла, т.к. тоже самое если поток тупо завершится после выполнения run()
или я ошибаюсь?


Название: Re: правильно грохнуть поток
Отправлено: Akon от Ноябрь 25, 2011, 17:55
Именно так. flag чтоб был volatile.
По поводу смысла - см. документацию, особенно на соответствующие нативные функции.


Название: Re: правильно грохнуть поток
Отправлено: LisandreL от Ноябрь 25, 2011, 18:01
мне надо, чтобы после нажатия на кнопку поток сразу сдох
чтобы не нужно было ждать пока run() до конца выполнится
Чудес не бывает.
Правильно - сообщить потоку, что он должен закончиться (флаг, слот…) и ждать когда он это сделает.
А убивание потока черевато разными штуками, вроде утечки памяти, незакрытых файлов, неразлоченных мьютексов прочей прелести.


Название: Re: правильно грохнуть поток
Отправлено: thechicho от Ноябрь 25, 2011, 18:07
эм. а если программу закрою? как быть?
при инициализации потока ставлю предка (this), гуи поток.
т.е. уничтожается главный поток, кот. в свою очередь убивает поток.
QThread: Destroyed while thread is still running
это нормально?
чота я совсем запутался.


Название: Re: правильно грохнуть поток
Отправлено: thechicho от Ноябрь 25, 2011, 18:11
// утечки памяти, незакрытых файлов, неразлоченных мьютексов прочей прелести
так после terminate(), вызывается finished()
Код
C++ (Qt)
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
т.е. деструктор вызывается в любом случае, где куча освободится... т.е. утечка какбэ не страшна...
работаю с файлами и мьютексы использую только в гуи потоке...
т.е. получается какбэ пофик, что он сдохнет в любой момент выполнения.


Название: Re: правильно грохнуть поток
Отправлено: BRE от Ноябрь 25, 2011, 18:11
это нормально?
Нет. Ты сам должен позаботиться о завершении потока перед закрытием программы (дать команду и дождаться завершения), тогда таких варнингов не будет.


Название: Re: правильно грохнуть поток
Отправлено: BRE от Ноябрь 25, 2011, 18:12
т.е. получается какбэ пофик, что он сдохнет в любой момент выполнения.
Ну тебе видней, если на все пофиг, то можно и терминайтить. :)


Название: Re: правильно грохнуть поток
Отправлено: Akon от Ноябрь 25, 2011, 21:46
немного оффтоп:
QProcess под завершение процесса имеет два слота: kill() и terminate() - вот и думай какой из них безобиднее  :)
terminate() - это корректный путь, следовало его назвать quit() что-ли.


Название: Re: правильно грохнуть поток
Отправлено: qt_user от Ноябрь 26, 2011, 19:06
если поток выполняет большую работу можно после каждой части делать проверку на флаг выхода:
Код
C++ (Qt)
void Thread::run
{
/*
   first work portion
*/

 
   if (stopped)
       return;
 
/*
   second work portion
*/

 
    if (stopped)
       return;
 
/*
   third work portion
*/

 
    if (stopped)
       return;
 
....
 
}
 

или же делать invokeMethod() пример тут: http://habrahabr.ru/blogs/qt_software/115835/ в самом конце


Название: Re: правильно грохнуть поток
Отправлено: thechicho от Ноябрь 28, 2011, 17:20
не догнал как invokeMethod() может помочь...
в общем так и сделал. 20 проверок воткнул на несколько сотен строк кода :D
это норм?^^

остался только вопрос. надо мьютексом защищать проверку флага?
тут http://www.youtube.com/watch?v=5WEiQ3VJfxc&feature=related (http://www.youtube.com/watch?v=5WEiQ3VJfxc&feature=related) (3:37) чувак защищает.


Название: Re: правильно грохнуть поток
Отправлено: LisandreL от Ноябрь 28, 2011, 19:58
тут http://www.youtube.com/watch?v=5WEiQ3VJfxc&feature=related (http://www.youtube.com/watch?v=5WEiQ3VJfxc&feature=related) (3:37) чувак защищает
Защищает? Локально объявленным мьютексом? *лицорука*


Название: Re: правильно грохнуть поток
Отправлено: qt_user от Ноябрь 28, 2011, 22:58
не догнал как invokeMethod() может помочь...
в общем так и сделал. 20 проверок воткнул на несколько сотен строк кода :D
это норм?^^

остался только вопрос. надо мьютексом защищать проверку флага?
тут http://www.youtube.com/watch?v=5WEiQ3VJfxc&feature=related (http://www.youtube.com/watch?v=5WEiQ3VJfxc&feature=related) (3:37) чувак защищает.

проверка\установка булевых переменных атомарные операции, защищать ничего ненужно
http://www.prog.org.ru/topic_20069_0.html


Название: Re: правильно грохнуть поток
Отправлено: qt_user от Ноябрь 28, 2011, 23:01
не догнал как invokeMethod() может помочь...
в общем так и сделал. 20 проверок воткнул на несколько сотен строк кода :D
это норм?^^
invokeMethod() может тебе помочь если у твою работу можно разбить на куски, и затем их вызывать
не напрямую, а слать в очередь событий Qt::QueuedConnection



Название: Re: правильно грохнуть поток
Отправлено: thechicho от Ноябрь 29, 2011, 23:22
// Защищает? Локально объявленным мьютексом? *лицорука*
ну я сам не бум-бум. и сложилось впечатление, что этот амер шарит, так что я категорично не могу согласиться, что он не прав...
мютексы такая хрень... как грится: "без пол-литра не разберешься" :D

хотя, как минимум, если "проверка\установка булевых переменных атомарные операции", мьютекс там нафик не нужен.

invokeMethod() думаю не понадобится.
в общем все заработало, как и задумывалось, фак йех)
сенкс за разъяснения :)

ВЫВОД: НЕ ИСПОЛЬЗУЙТЕ terminate(); !!!
ТОЛЬКО ФЛАГИ и никак иначе.