Russian Qt Forum

Qt => Вопросы новичков => Тема начата: demaker от Декабрь 10, 2014, 16:21



Название: QThread
Отправлено: demaker от Декабрь 10, 2014, 16:21
Создается поток по нажатию и запускается по нажатию кнопки
но почему-то при закрытии виджета поток все еще остается, хотя в
деструкторе я его убиваю.
Подскажите в чем причина  ???

Код
C++ (Qt)
void Widget::createThread()
{
...
thread = new Thread();
thread->start();
 
}
 
void Widget::~Widget()
{
 if(thread->isRunning()){
    thread->quit();
    thread->wait();
    thread->deleteLater();
}
}
 
 


Название: Re: QThread
Отправлено: torwig от Декабрь 10, 2014, 16:34
Может потому, что deleteLater() не сразу удаляет обьект.
А как Вы определяете, что он все еще остается?


Название: Re: QThread
Отправлено: ecspertiza от Декабрь 10, 2014, 16:37
deleteLater() удалит поток когда:

1. Он перестанет работать.
2. На него никто не будет ссылаться.

Возникает вопрос, что внутри потока ?


Название: Re: QThread
Отправлено: demaker от Декабрь 10, 2014, 16:38
по выводу сообщения в консоль из потока через дебаг
Код
C++ (Qt)
void Thread::run()
{
 forever(){
   qDebug()<<"Thread";
   funcWait(20); //20 msec
}
}
 



Название: Re: QThread
Отправлено: demaker от Декабрь 10, 2014, 17:15
Ступил, понял
надо делать так:

Код
C++ (Qt)
void Widget::createThread()
{
...
thread = new Thread();
thread->threadStart = true;
thread->start();
 
}
 
void Widget::~Widget()
{
 if(thread != NULL){
    thread->startThread = false
    thread->quit();
    thread->wait();
    thread->deleteLater();
 
void Thread::run(){
 
 forever(){
 if(!threadStart){
   break;
 }
...
}
 


Название: Re: QThread
Отправлено: Alexu007 от Декабрь 10, 2014, 19:01
А почему deleteLater()? Обычный delete() чем плох?


Название: Re: QThread
Отправлено: Igors от Декабрь 11, 2014, 12:40
deleteLater() удалит поток когда:

1. Он перестанет работать.
2. На него никто не будет ссылаться.
Не знаю как можно сослаться на поток, прошу привести пример. И по-моему если поток и работает - все равно удалится (некорректно, ошибка в консоли).

deleteLater засылает событие на удаление в текущий EventLoop, удаление будет выполнено когда дело дойдет до этого события. Это иногда удобно, но операция опасная, не надо использовать ее без необходимости.


Название: Re: QThread
Отправлено: Bepec от Декабрь 11, 2014, 16:29
Операция с тем же риском, что и new и delete. Если не изгаляться и думать при написании об архитектуре, то всё будет нормально.


Название: Re: QThread
Отправлено: Igors от Декабрь 12, 2014, 10:22
Операция с тем же риском, что и new и delete. Если не изгаляться и думать при написании об архитектуре, то всё будет нормально.
Тогда поясните что должно происходить в примере выше
Код
C++ (Qt)
if(thread != NULL){
    thread->startThread = false
    thread->quit();
    thread->wait();
    thread->deleteLater();
- в какой (или чей) EventLoop будет помещено событие удаления?
- когда оно будет извлечено и произойдет удаление thread?


Название: Re: QThread
Отправлено: Old от Декабрь 12, 2014, 13:30
- в какой (или чей) EventLoop будет помещено событие удаления?
- когда оно будет извлечено и произойдет удаление thread?
А вы готовы утверждать в чей eventloop попадет событие по тем отрывкам кода, который есть в теме?
Очень интересно. :)


Название: Re: QThread
Отправлено: demaker от Декабрь 12, 2014, 14:49
так как правильно ???
Код:
delete...
или
Код:
...->deleteLater();


Название: Re: QThread
Отправлено: Old от Декабрь 12, 2014, 14:52
так как правильно ???
В вашем случае достаточно простого delete.


Название: Re: QThread
Отправлено: Igors от Декабрь 12, 2014, 15:26
А вы готовы утверждать в чей eventloop попадет событие по тем отрывкам кода, который есть в теме?
А чего мне утверждать - я лучше спрошу у того кто делает такие авторитетные заявления
Операция с тем же риском, что и new и delete. Если не изгаляться и думать при написании об архитектуре, то всё будет нормально.
Пусть он разъясняет/утверждает  :)


Название: Re: QThread
Отправлено: Old от Декабрь 12, 2014, 15:38
Вы задаете вопросы, для ответов на которые не хватает информации и просите разяснить или утвердить? :)


Название: Re: QThread
Отправлено: Igors от Декабрь 12, 2014, 17:03
Вы задаете вопросы, для ответов на ..
Ну что Вы, право, как орел защищающий птенца-Вереса :) Нечего его защищать, как всегда ляпнул не подумавши - пусть отвечает. А для Вас я запостил тему про темплейты, лучше там ответьте


Название: Re: QThread
Отправлено: Bepec от Декабрь 12, 2014, 17:16
EventLoop будет Widget. Так что спокойно встанет, дождётся выключения потока и успешно удалится.




Название: Re: QThread
Отправлено: Old от Декабрь 12, 2014, 17:17
А для Вас я запостил тему про темплейты, лучше там ответьте
Я саму разберусь, в какой теме мне отвечать, а в какой нет.

Нечего его защищать, как всегда ляпнул не подумавши - пусть отвечает.
И сам решу, кого мне защищать, а кого нет. К тому же я никого не защищаю, скорее по этому вопросу думаю также.
Это вы ваши сложности с deleteLater и вообще с очередями сообщений, пытаетесь представить вселенской опасностью. А она яйца выеденного не стоит, если понимать, что делаешь.А по другому, лучше ничего не делать.


Название: Re: QThread
Отправлено: Old от Декабрь 12, 2014, 17:20
EventLoop будет Widget. Так что спокойно встанет, дождётся выключения потока и успешно удалится.
А если объект класса Thread делает moveToThread?


Название: Re: QThread
Отправлено: Igors от Декабрь 12, 2014, 18:12
EventLoop будет Widget.
Неверно (по крайней мере в общем случае)
Так что спокойно встанет, дождётся выключения потока и успешно удалится.
Тоже неверно, никто никого дожидаться не будет


Название: Re: QThread
Отправлено: Old от Декабрь 12, 2014, 18:16
Неверно (по крайней мере в общем случае)
Как раз в общем случае верно, объект QThread будет принадлежать создающей его нитке, а не порождаемой им.

Тоже неверно, никто никого дожидаться не будет
Тут не знаю про что вы говорите. :)


Название: Re: QThread
Отправлено: Igors от Декабрь 12, 2014, 19:30
Как раз в общем случае верно, объект QThread будет принадлежать создающей его нитке, а не порождаемой им.
Так это называется "по умолчанию" и к общности отношения не имеет.

Тут не знаю про что вы говорите. :)
Просто когда дело дойдет до события DeferredDelete (порожденного deleteLater), то объект удалится невзирая на  "незавершенный поток".

Это вы ваши сложности с deleteLater и вообще с очередями сообщений, пытаетесь представить вселенской опасностью. А она яйца выеденного не стоит, если понимать, что делаешь.А по другому, лучше ничего не делать.
Никогда не боялся очередей. Да, получал неск раз по ушам, но гораздо меньше чем в др местах. Вернемся к первоисточнику
Код
C++ (Qt)
if(thread != NULL){
    thread->startThread = false
    thread->quit();
    thread->wait();
    thread->deleteLater();
Вы совершенно правильно указали что без контекста невозможно предсказать поведение deleteLater. Весьма вероятно где-то выше понадобится
Код
C++ (Qt)
thread->moveToThread(thread)
Иначе какой смысл крутить там EventLoop? Но тогда событие DeferredDelete будет помещено в очередь thread - но она уже остановлена (thread->quit()). Когда же удалится  thread? Наверное никогда (без доп действий). Почему "наверное" - ну хз, может у Qt есть доп процессинг для этого случая (вряд ли, но не проверял).

Спрашивается: а за каким <template> было так делать, искать ненужных приключений? Чем было плохо простецкое delete? Зачем надо было продлевать жизнь thread? Что хотели еще от нее получить? Это называется "понимать что делаешь"? Совсем наоборот. Тоже мне, сокол защищающий выеденные яйца  :)


Название: Re: QThread
Отправлено: Old от Декабрь 12, 2014, 19:37
Это называется "понимать что делаешь"? Совсем наоборот.
Смешались в кучу кони люди... :) Ну да ладно.



Название: Re: QThread
Отправлено: Bepec от Декабрь 12, 2014, 20:15
Igors в общем случае поведение будет согласно моему сообщению. А вот перенос QThread moveToThread как раз отдельный случай.

Зачем ждать? потому что поток может быть занят вычислениями. Ему пофиг что там кто-то где-то приказал завершаться :) И он будет заканчивать заданную ему работу. Именно на этот случай и сделан Wait, дающий ему время на корректное и заложенное по умолчанию завершение.

И да, deleteLater тут возможно избыточен, но тем не менее он сработает и будет всё хорошо :)

И скорее всего ситуация с вызовом deleteLater из собственного потока обрабатывается Qt. Ибо ни разу не имел с deleteLater утечек памяти.

PS попадал однажды в похожую ситуацию с потоками, но давно. К сожалению найти исходников не смог.


Название: Re: QThread
Отправлено: Igors от Декабрь 12, 2014, 20:57
Зачем ждать? потому что поток может быть занят вычислениями. Ему пофиг что там кто-то где-то приказал завершаться :) И он будет заканчивать заданную ему работу.
Никто никого не ждет - сказали удалить QThread - и этот объект будет удален, занимаемая им память станет доступной для других. Если поток (порожденный этой QThread) еще работает (используя удаленные данные) - ну вылетит, c'est la vie

Именно на этот случай и сделан Wait, дающий ему время на корректное и заложенное по умолчанию завершение.
Ничего он не дает и никаких умолчаний нет. Это просто останов текущей нитки до тех пор пока указанная не завершится - и все (см pthread_join). Если указанная не собирается завершаться  - текущая ждет forever