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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Остановка потока при уничтожении QThread  (Прочитано 13267 раз)
Осенний дождь
Гость
« : Май 23, 2007, 12:00 »

Доброе время суток.

Господа, у меня теоретический вопрос. Почему при уничтожении объекта QThread не завершается поток который он обслуживал?

Вот цитата из документации по Qt 4.2.2

Цитировать
Note that deleting a QThread object will not stop the execution of the thread it represents. Deleting a running QThread (i.e. isFinished() returns false) will probably result in a program crash. You can wait() on a thread to make sure that it has finished.


Кто-нибудь знает почему так сделано?
Записан
goer
Гость
« Ответ #1 : Май 23, 2007, 14:29 »

Дык, тут же и ответ:

Цитировать
Deleting a running QThread (i.e. isFinished() returns false) will probably result in a program crash. You can wait() on a thread to make sure that it has finished.
Записан
Осенний дождь
Гость
« Ответ #2 : Май 23, 2007, 18:57 »

Тут написано, что удаление запущенного потока опасно, но если программист все же решил удалить этот объект разумнее остановить поток!
В этом случае мы можем получить области данных в которых не был завершен процес модификации данных, заблокированные mutex и симофоры и т.д. Однако, если удалить объект не завершая поток, то рискуем получить еще худшую ошибку. Исполняемый код функции run() будет находиться в освобождаемой области данных и в результате программа выполнит недопустимую операцию или обратиться к недопустимому адресу.

Можете ли вы привести пример когда объект можно уничтожить не завершая поток (при условии что поток все еще выполняется)?
Записан
goer
Гость
« Ответ #3 : Май 23, 2007, 19:33 »

А зачем объект уничтожать не завершая поток? Уничтожать объект QThreda надо только после того как он закончит свою работу, для этого они и рекомендуют в общем случае ставить wait() в деструкторе. Правда это не обязательно.

Отследить момент когда поток должен быть остановлен нужно самому, затем остановить его и можно безболезненно удалять тем же delete(). Вот только не факт, что поток остановится сразу после вызова exit(). Для этого и рекомендуют ставить wait()  в деструкторе.

Это просто рекомендация, как с  умными указателеями: никто не говорит что это единственно правильный путь, но он гораздо легче остальных.
Записан
Осенний дождь
Гость
« Ответ #4 : Май 24, 2007, 10:27 »

Мы не вполне понимаем друг друга. Улыбающийся

Попробую сказать по другому. Представте, что вы автор библиотеки Qt. И вот, вы приступили к написанию класса QThread. Добавили бы вы вызов terminate() в деструктор QThread? Я бы добавил. Класс уничтожается и значит поток с котором он был ассоциирован должен быть завершен. Это логично. Он авторы поступили по другому и мне интересно какие у них были причины.
Записан
goer
Гость
« Ответ #5 : Май 24, 2007, 10:52 »

Читаем еще раз.

НИ terminate(), НИ exit() НЕ гарантируют что поток будет немедленно остановлен. Дальше понятно?
Записан
Emc
Гость
« Ответ #6 : Май 24, 2007, 11:13 »

Цитата: "goer"

НИ terminate(), НИ exit() НЕ гарантируют что поток будет немедленно остановлен.

что вобщем то правильно - единственный разумный подход
создать флаг в Thread::run глобальный естественно - чтоб можно изменить извне - вот, далее там же (в теле run) ставим проверки
if (!flag) return; и на signal QThread::finished() вешаем слот с thread->delateLater();

гарантированно работает - позволяет прерывать thread в любой момент
Записан
goer
Гость
« Ответ #7 : Май 24, 2007, 11:35 »

Цитата: "Emc"
Цитата: "goer"

НИ terminate(), НИ exit() НЕ гарантируют что поток будет немедленно остановлен.

что вобщем то правильно - единственный разумный подход
создать флаг в Thread::run глобальный естественно - чтоб можно изменить извне - вот, далее там же (в теле run) ставим проверки
if (!flag) return; и на signal QThread::finished() вешаем слот с thread->delateLater();

гарантированно работает - позволяет прерывать thread в любой момент


А еще можно через wait()  в деструкторе или через кучу других способов. Тут уж кто как считает разумнее.

Если "Осенний дождь" интересуют технические детали почему невозможно взять и остановить поток в любой момент, то он может поковырятся в сорцах... винды, юникса, мака.

Да и вобще, даже если не вникать в такие подробности - если поток например, принимает данные из сети, как ты предлагаешь его останавливать? В лоб удалять сокеты принимающие данные? Вряд ли юзеру понравится окошко с предложением отправить отчет МС-у.
Записан
Alex03
Гость
« Ответ #8 : Май 24, 2007, 11:36 »

Цитата: "Осенний дождь"

Попробую сказать по другому. Представте, что вы автор библиотеки Qt. И вот, вы приступили к написанию класса QThread. Добавили бы вы вызов terminate() в деструктор QThread? Я бы добавил. Класс уничтожается и значит поток с котором он был ассоциирован должен быть завершен. Это логично. Он авторы поступили по другому и мне интересно какие у них были причины.


Что делает поток - знаете только Вы. Тупо прибивать отдельный поток - имеет змысл очень редко (чаще вместе со всем приложением). Практически в любом маломальски значительном потоке будут как минимум динамическое выделение памяти, не говоря уж о всяких блокировках, работе с девайсами и т.д. И как следствие - утечки памяти (и прочий гемор) при убийстве потока.

Ну а если Вам действительно нужен terminate() в деструкторе - так всё ж в Ваших руках.
Но лучше всё-же контролировать какойнить объект синхронизации в потоке, и завершаться по соответствующему условию.
Записан
Emc
Гость
« Ответ #9 : Май 24, 2007, 12:48 »

Цитировать
А еще можно через wait()  в деструкторе или через кучу других способов

wait ждет завершения работы потока --- мой способ прерывает его в любой момент
куча других способов -- очень интересно
примеры пожалуйста -- действительно интересно - мой подход с флагом имеет кучу недостатков - хотелось бы найти действительно хороший вариант
Записан
goer
Гость
« Ответ #10 : Май 24, 2007, 14:24 »

Общая стратегия, как правильно писал Alex03, это контролировать объект синхронизации в потоке. В данном случае просто флаг - слишком примитивный объект синхронизации. От задачи к задаче реализация будет менятся и искать единственно правильный вариант в программировании вообще, простите, глупо.
Записан
Emc
Гость
« Ответ #11 : Май 24, 2007, 15:40 »

угу только вот не всегда синхронизация нужна
ну я так понимаю кроме как ввода спец. проверки для принудительного выхода из QThread::run никто предложить не может --- одни рассуждения о множестве вариантов
пожалуйста приведите конкретный пример с qt кодом

у меня самого программа использует qthread и мне очень хотелось бы увидеть способы принудительного завершения
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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