Название: Остановка потока при уничтожении QThread Отправлено: Осенний дождь от Май 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. Кто-нибудь знает почему так сделано? Название: Остановка потока при уничтожении QThread Отправлено: goer от Май 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. Название: Остановка потока при уничтожении QThread Отправлено: Осенний дождь от Май 23, 2007, 18:57 Тут написано, что удаление запущенного потока опасно, но если программист все же решил удалить этот объект разумнее остановить поток!
В этом случае мы можем получить области данных в которых не был завершен процес модификации данных, заблокированные mutex и симофоры и т.д. Однако, если удалить объект не завершая поток, то рискуем получить еще худшую ошибку. Исполняемый код функции run() будет находиться в освобождаемой области данных и в результате программа выполнит недопустимую операцию или обратиться к недопустимому адресу. Можете ли вы привести пример когда объект можно уничтожить не завершая поток (при условии что поток все еще выполняется)? Название: Остановка потока при уничтожении QThread Отправлено: goer от Май 23, 2007, 19:33 А зачем объект уничтожать не завершая поток? Уничтожать объект QThreda надо только после того как он закончит свою работу, для этого они и рекомендуют в общем случае ставить wait() в деструкторе. Правда это не обязательно.
Отследить момент когда поток должен быть остановлен нужно самому, затем остановить его и можно безболезненно удалять тем же delete(). Вот только не факт, что поток остановится сразу после вызова exit(). Для этого и рекомендуют ставить wait() в деструкторе. Это просто рекомендация, как с умными указателеями: никто не говорит что это единственно правильный путь, но он гораздо легче остальных. Название: Остановка потока при уничтожении QThread Отправлено: Осенний дождь от Май 24, 2007, 10:27 Мы не вполне понимаем друг друга. :)
Попробую сказать по другому. Представте, что вы автор библиотеки Qt. И вот, вы приступили к написанию класса QThread. Добавили бы вы вызов terminate() в деструктор QThread? Я бы добавил. Класс уничтожается и значит поток с котором он был ассоциирован должен быть завершен. Это логично. Он авторы поступили по другому и мне интересно какие у них были причины. Название: Остановка потока при уничтожении QThread Отправлено: goer от Май 24, 2007, 10:52 Читаем еще раз.
НИ terminate(), НИ exit() НЕ гарантируют что поток будет немедленно остановлен. Дальше понятно? Название: Остановка потока при уничтожении QThread Отправлено: Emc от Май 24, 2007, 11:13 Цитата: "goer" НИ terminate(), НИ exit() НЕ гарантируют что поток будет немедленно остановлен. что вобщем то правильно - единственный разумный подход создать флаг в Thread::run глобальный естественно - чтоб можно изменить извне - вот, далее там же (в теле run) ставим проверки if (!flag) return; и на signal QThread::finished() вешаем слот с thread->delateLater(); гарантированно работает - позволяет прерывать thread в любой момент Название: Остановка потока при уничтожении QThread Отправлено: goer от Май 24, 2007, 11:35 Цитата: "Emc" Цитата: "goer" НИ terminate(), НИ exit() НЕ гарантируют что поток будет немедленно остановлен. что вобщем то правильно - единственный разумный подход создать флаг в Thread::run глобальный естественно - чтоб можно изменить извне - вот, далее там же (в теле run) ставим проверки if (!flag) return; и на signal QThread::finished() вешаем слот с thread->delateLater(); гарантированно работает - позволяет прерывать thread в любой момент А еще можно через wait() в деструкторе или через кучу других способов. Тут уж кто как считает разумнее. Если "Осенний дождь" интересуют технические детали почему невозможно взять и остановить поток в любой момент, то он может поковырятся в сорцах... винды, юникса, мака. Да и вобще, даже если не вникать в такие подробности - если поток например, принимает данные из сети, как ты предлагаешь его останавливать? В лоб удалять сокеты принимающие данные? Вряд ли юзеру понравится окошко с предложением отправить отчет МС-у. Название: Остановка потока при уничтожении QThread Отправлено: Alex03 от Май 24, 2007, 11:36 Цитата: "Осенний дождь" Попробую сказать по другому. Представте, что вы автор библиотеки Qt. И вот, вы приступили к написанию класса QThread. Добавили бы вы вызов terminate() в деструктор QThread? Я бы добавил. Класс уничтожается и значит поток с котором он был ассоциирован должен быть завершен. Это логично. Он авторы поступили по другому и мне интересно какие у них были причины. Что делает поток - знаете только Вы. Тупо прибивать отдельный поток - имеет змысл очень редко (чаще вместе со всем приложением). Практически в любом маломальски значительном потоке будут как минимум динамическое выделение памяти, не говоря уж о всяких блокировках, работе с девайсами и т.д. И как следствие - утечки памяти (и прочий гемор) при убийстве потока. Ну а если Вам действительно нужен terminate() в деструкторе - так всё ж в Ваших руках. Но лучше всё-же контролировать какойнить объект синхронизации в потоке, и завершаться по соответствующему условию. Название: Остановка потока при уничтожении QThread Отправлено: Emc от Май 24, 2007, 12:48 Цитировать А еще можно через wait() в деструкторе или через кучу других способов wait ждет завершения работы потока --- мой способ прерывает его в любой момент куча других способов -- очень интересно примеры пожалуйста -- действительно интересно - мой подход с флагом имеет кучу недостатков - хотелось бы найти действительно хороший вариант Название: Остановка потока при уничтожении QThread Отправлено: goer от Май 24, 2007, 14:24 Общая стратегия, как правильно писал Alex03, это контролировать объект синхронизации в потоке. В данном случае просто флаг - слишком примитивный объект синхронизации. От задачи к задаче реализация будет менятся и искать единственно правильный вариант в программировании вообще, простите, глупо.
Название: Остановка потока при уничтожении QThread Отправлено: Emc от Май 24, 2007, 15:40 угу только вот не всегда синхронизация нужна
ну я так понимаю кроме как ввода спец. проверки для принудительного выхода из QThread::run никто предложить не может --- одни рассуждения о множестве вариантов пожалуйста приведите конкретный пример с qt кодом у меня самого программа использует qthread и мне очень хотелось бы увидеть способы принудительного завершения |