Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Принудительно уничтожить поток(TThread) с корректн


Автор: Pcrepair 4.6.2013, 22:01
Добрый день. Есть программа многопоточной загрузки с обработкой HTML-странииц
Программа работает, но иногда попадаются файлы большого размера(10 мб, например http://www.techboard.ru/thread.php?cid=6&scid=10&page=2546) с большим количеством ссылок внутри.
загрузчик (TidHttp) загружает страницу достаточно быстро(40 сек) и гарантированно, но обработка такой страницы доходит до 30 мин и завершается корректно, однако времени ждать такую страницу нет, желательно нажать на батон и завершить такой поток, но корректно
Вопросы:
- возможно ли это в принципе? с корректным освобождением ресурсов
- если возможно, то как конкретно это сделать, желательно пример

Автор: Poseidon 4.6.2013, 22:56
Вот просмотри http://forum.vingrad.ru/forum/topic-163841/kw-tthread-потоки-многопоточность-threads/hl/%25D0%25BF%25D0%25BE%25D1%2582%25D0%25BE%25D0%25BA/index.html. Там показан один из вариантов как можно "попросить" поток остановится нажатием кнопки.

Автор: boobie 6.6.2013, 07:12
Код

твой_поток.suspend;//приостановить выполнение. В новых версиях Дельфи не рекомендуется
твой_поток.suspended:=true;//приостановить поток. Рекомендуется использовать вместо suspend
твой_поток.terminate;//завершить выполнение потока. Если не ошибаюсь, происходит мягкое завершение - не сразу, дожидается логического завершения.

Корректное освобождение ресурсов, я думаю, это проблема уже программиста.

Автор: Poseidon 6.6.2013, 11:55
Цитата(boobie @  6.6.2013,  07:12 Найти цитируемый пост)
твой_поток.terminate;//завершить выполнение потока. Если не ошибаюсь, происходит мягкое завершение - не сразу, дожидается логического завершения.
terminate всего-лишь устанавливает свойство Terminated в True. Само по себе поток не останавливает. Программист должен сам в теле потока позаботится о проверке свойства Terminated и завершить поток.

Автор: bems 7.6.2013, 02:05
для начала, я думаю, нужно сделать что-то с получасовым парсингом

Автор: Akella 7.6.2013, 08:52
Начало отседава http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1027288&msg=14392799

Автор: MetalFan 18.6.2013, 10:14
Akella, имхо, чтобы ТС не путался в терминологии и уложил кашу по потокам в голове в порядок, надо в первую очередь изучить мегаопус http://forum.vingrad.ru/forum/topic-60076/view-all.html#.

Автор: Akella 18.6.2013, 13:29
Да, долго его придётся изучать.
Но там нет одной важной фишки: в потоках лучше не использовать sleep(), а что вместо этого использовать?

Автор: MetalFan 18.6.2013, 13:50
Akella, почему? хотя какой смотря таймаут использовать... если sleep(1)/SleepEx(1, true) к примеру, то, имхо, ничего страшного... но лучше, конечно, использовать Wait-функции для ожидания внутри потока.

Автор: Poseidon 18.6.2013, 14:40
Цитата(Akella @ 18.6.2013,  13:29)
в потоках лучше не использовать sleep(), а что вместо этого использовать?

Я чего-то может недопонимаю, но расскажите мне ситуацию, в которой нужно использовать sleep в потоках

Автор: MetalFan 18.6.2013, 15:12
Poseidon, ну, к примеру, крутится поток в бесконченом цикле, ждет чего-то... чтобы проц не грузил, втыкаем sleep с небольшим таймаутом. 
Но это явно показывает, что есть недочеты в алгоритме работы потока.

Автор: Akella 18.6.2013, 16:27
Представим, что программа раз в 45 минут выполняет некую операцию, например, сохранение данных в XML. Сама операция (процедура экспорта в XML) длиться 30 секунд.
Как корректно завершить нить, чтобы правильно освободились все ресурсы, объекты и т.д.?
Если вызвать terminated у потока, то поток будет ждать пока закончится sleep только потом завершиться.
Пользователь решил завершить работу программы. Нажал Выход.... и всё - программа зависла. Пользователю что, ждать пол часа пока отработает оставшееся время, указанное в sleep?
Да, можно закрыть принудительно, но будет ли это правильно?


Добавлено @ 16:28
Я переделал на EVENT и теперь всё чики-пики smile

Добавлено @ 16:29
А если использовать sleep(45 минут), то нить тупо зависает на это время. Как ты дашь знать потоку что нужно завершиться ,если поток сейчас в глубоком sleep`е?

Автор: bems 18.6.2013, 21:50
Цитата(Akella @  18.6.2013,  16:27 Найти цитируемый пост)
А если использовать sleep(45 минут), то нить тупо зависает на это время. Как ты дашь знать потоку что нужно завершиться ,если поток сейчас в глубоком sleep`е? 
ну тогда SleepEx

Автор: Poseidon 18.6.2013, 22:46
Цитата(MetalFan @ 18.6.2013,  15:12)
Poseidon, ну, к примеру, крутится поток в бесконченом цикле, ждет чего-то... чтобы проц не грузил, втыкаем sleep с небольшим таймаутом. 
Но это явно показывает, что есть недочеты в алгоритме работы потока.

Верно, это ошибка алгоритма работы. Но это не говорит о том, что все, хана, без sleep никак. Зачем крутить цикл в холостую? Правильнее будет запускать поток при возникновении "чего-то". Я вообще не понимаю использование sleep в программах. Единственное место где это более-менее оправдано, это работа с сетью. Но слипы более секунды тоже говорят об ошибках алгоритма. 

Автор: MetalFan 19.6.2013, 08:29
Цитата(Poseidon @  18.6.2013,  22:46 Найти цитируемый пост)
Но слипы более секунды тоже говорят об ошибках алгоритма.

полностью согласен.

Цитата(Akella @  18.6.2013,  16:27 Найти цитируемый пост)
Я переделал на EVENT

Вот и правильное решение. Event (а можно и его обертку SyncObjs.TEvent), можно и нужно использовать в качестве "флага" того, что потоку надо что-то сделать.
А вместо sleep/suspend/resume/suspended юзать WaitForSingleObjectEx/TEvent.WaitFor SetEvent/ResetEvent

И получится и потокобезопасно и архитектурно-правильное решение.

Автор: Akella 19.6.2013, 13:53
MetalFan, ну вот smile, а ты спрашивал почему.

Автор: MetalFan 20.6.2013, 09:19
Akella, нет, ну в крайних случаях можно и SleepEx(1) вставить)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)