Здравствуйте. Есть поток, который в цикле делает кое-какую работу (взаимодействует с сетью). Когда подана команда его завершения - свойство Terminated становится true. Таким образом, чтобы завершить работу потока, нужно в цикле его работы проверять значение этого свойства. Code: while(true) { if(this->Terminated) { ... ... ... } ... ... ... } Но всё дело в том, что время итерации кода может достигать нескольких минут, а завершить всё надо быстро. Поэтому, возникала идея проверять Terminated при каждой отправке данных на сервер. Будет ли рационально делать так? Ибо таких вот "отправок" есть очень много, и после каждой вставлять этот код мне кажется не очень правильным решением.
WaitForSingleObject не годится? Сам ждет терминирования, ждет указанное время. Я бы в главном потоке (поток-арбитр) сделал ожидание завершения других, а весь остальной код разбил бы по другим потокам.
Не то. WaitForSingleObject ждёт завершения потока. А мне нужно, чтобы поток завершился по моему желанию, тоесть в любой момент времени. В классе TThread есть свойство функция Terminate, которая присваивает флажку Terminated значение true. Но где именно его проверять, чтобы завершение прошло быстро и рационально?
TerminateThread никак не подходит, потому что он завершает поток, а все объекты так и остаются "плавать" в памяти программы. Об этом я испрашивал, перечитай пост. Мне кажется, будет нерационально после каждой функции проверять terminated...
Обычно значение поля Terminated проверяют в начале цыкла. Но если ты говоришь, что проход по цыклу может занимать длительное время, то все таки лучше делать проверку Terminated в нескольких местах кода. Мне кажеться, что это не правильно, если пользователь нажмет в программе кнопку "Стоп" и все потоки немедленно завершаться (то есть убить всех каким то способом из главного). Лучше делать именно проверку Terminated и завершать в потоке "самого себя" так, как надо.
Понятное дело, поэтому и не использую TerminateThread и ей подобные. Я не говорил, что проверка Terminated - неправильна. Просто проверять её во многих местах мне кажется как минимум - некорректо.
Лучше всего проверять значение Terminated перед отправкой следующего запроса. Если тебя смущает большое количество проверок, можно поступить следующим образом. Если ты используешь ООП в своей работе, то можешь настроить события для компонента, например, который отвечает за работу с сетью. У всех нормальных компонентов/классов присутсвуют события, которые возникают перед стартом работы. Так вот можешь запрограммировать эти события, и твой код не только начнет смотреться читабельние, но и все будет правильно работать.
А я вот не суеверен. Качать файл 100МБ "одной строкой" да ещё и через инди - убожество У меня есть несколько вложенных циклов, которые выполняют кое-какую работу. В основном вся задержка - на приём и отправку запросов (их много). Поэтому в начало рабочего цикла не вариант. Тогда, всё же, буду использовать проверку в теле каждого вложенного цикла.
Code: Var S : TFileStream; Begin S := TFileStream.Create('C:\temp.html', fmCreate); try IdHTTP.Get('http://site.ru', S); finally S.Free; end; Фактически одной строкой, в чем же тут убожество?) Indy хорошая библиотека. Да...раньше багов было много, но щас практически все поправили(Я о 10-ой версии, к примеру в Delphi XE). Чтобы через определенное количество байт делать проверку при загрузки - можно использовать событие OnWork. На счет проверок, я бы сделал так : Code: type TThreadTerminateException = class(Exception); procedure TMyThread.Execute; procedure CheckTerminate; Begin if Terminated then raise TThreadTerminateException.Create(''); end; Begin try try //Основной код потока //... CheckTerminate; //Проверка на завершение потока. //... finally //действия, выполняемые в конце потока end; except on e1:TThreadTerminateException Begin //действия, если поток завершился аварийно end; on e2:Exception Begin //Выполнить действия, если просто произошло не определенное исключение end; end; end;
CheckTerminate можно вообщем вывести в сам класс потока и если вызываешь внешние функции внутри потока, то в них можно так же передавать ссылку на данный класс потока и собсна уже в них проверять активность.
Как я понял у ТСа код наподобие этого: while (true) { // тут строк 10 низкоуровной работы с сетью // тут проверка // еще строк 10 низкоуровной работы с сетью // тут опять проверка // тут вложенный цикл и в нем еще много таких подобных участков } что по мне есть аццкий быдлокот ибо все эти участки весьма похожи. это дублирование кода я бы вынес выполнение запросов в отдельный класс, куда передается параметрами то что нужно отправить. а в этот класс внес событие, что-то вроде OnAfterRequest, соответственно вызываемое после каждого запроса. Код работающий с классом подписывается на него, где проверяет на Terminated, если true то генерится ексепшн, ибо это единственный способ выйти и из вызывающих методов. Но, судя по некоторым репликам ТСу глубоко начхать на good practices, он и будет дальше писать огромные циклы и дублировать однотипный код.
А мне кажется что это перебор, если пишешь какой нить универсальный код из стопицот модулей, который можно будет использовать для множества прог, то да. Нужно писать относительно задачи, а не раздувать...раздувать если проект на много лет, а не ради красоты кода. Без этого в данной задаче никак, будешь дублировать текст - профит от раздувательства будет не лучше.