Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Вопрос про TThread


Автор: кварк 10.9.2002, 16:39
Поток выполняет некоторые действия.
Как лучше организовать откат?

У меня сейчас так:
Execute
begin
 phase 1
 if not terminated then phase 2
 if not terminated then phase 3
  . . .
 if not terminated then phase n

 if terminated then
  откат с последней выполненой фазы
end

Может, есть способы лучше, проще и элегантней?

P.S. Вопрос задан, чтобы узнать "как люди делают". - Хочется ведь делать грамотно :)

Автор: Dapo 10.9.2002, 20:10
А у вас это работает? По-моему не должно.

Пример использования с-ва Terminated:

phase1;
while not Terminated do
begin  
 phase2;
 ....
 phaseN;
end;

Команда Terminate устанавливает флаг Terminated в true и немедленно прерывает поток, другими словами код типа:
......
if terminated then
 dosomething(...);
......
вообще не выполнится.

Для того чтобы выполнить какие-то действия в момент остановки потока, нужно использовать его событие OnTerminate. Причем оно вызывается и на команду Terminate (в этом случае поток все равно прерывается), и на doTerminate - метод объекта TThread (в этом случае событие OnTerminate вызывается, но поток не прерывается.) Следовательно, для того чтобы отловить момент завершения потока, нужно передавать какой-нибудь флаг в руки... :) точнее, в Execute потока по которому вызывать(или не вызывать) метод DoTerminate. Поправте если что не так.

Автор: кварк 10.9.2002, 20:50
Вроде, работает.
У меня теперь, правда, несколько по другому:
try
phase 1
if not terminated then phase 2
if not terminated then phase 3
 . . .
if not terminated then phase n
finally
 if terminated then
   откат с последней выполненой фазы
end

А потом, как я понял из Delphi help, TThread.Terminate ставит свойство Terminated в true, а не завершает поток немедленно. На практике, вроде, тоже самое.

Автор: Dapo 11.9.2002, 12:09
Цитата
А потом, как я понял из Delphi help, TThread.Terminate ставит свойство Terminated в true, а не завершает поток немедленно. На практике, вроде, тоже самое.

Да, на счет "немедленно" - я погорячился. Terminate  устанавливает св-во Terminated в True, которое показывает что поток будет прерван ТАК СКОРО НА СКОЛЬКО ЭТО ВОЗМОЖНО. В API по-другому, там поток завершается именно "немедленно ". Даже не знаю, что удобнее  ???

Автор: Fantasist 12.9.2002, 14:41
Цитата
Terminate  устанавливает св-во Terminated в True, которое показывает что поток будет прерван ТАК СКОРО НА СКОЛЬКО ЭТО ВОЗМОЖНО


Ну показывает это чисто условно. Скорее это предложение потоку завершиться, а так, как ты сам контролируешь Execute, то завершиться он или нет решать тебе.
Цитата

В API по-другому, там поток завершается именно "немедленно"


Так в API и классов нет.  :D
А делфийский TThread - это обертка над API, так что как только ты выйдешь из своего Execute, поток "немедленно" завершится. Почти. Он еще выполнит еще эти строчки:
Код

   FreeThread := Thread.FFreeOnTerminate;
   Result := Thread.FReturnValue;
   Thread.FFinished := True;
   Thread.DoTerminate;
   if FreeThread then Thread.Free;
   EndThread(Result);

В тот момент, как функция EndThread вернет значение, поток только что был завершен. Но все эти строчки выполняться уже после твоего кода.

Автор: Le Taon 27.9.2002, 06:28
Цитата
В API по-другому, там поток завершается именно "немедленно ". Даже не знаю, что удобнее


И в API также. Поток завершается, когда ф-я потока возвращает управление.
(В случае с TThread поток завершается, когда завершается ф-я ThreadWrapper)

В API действительно есть ещё ф-и ExitThread и TerminateThread, к-рые насильственно завершают поток.
Но пользоваться ими рекомендуется только в крайнем случае, если, например, поток завис (поскольку это запросто может привести к утечке ресурсов, а то и к чему-нибудь похуже).
Так что слово "удобство" к ним неприменимо.

И если уж на то пошло, применить их можно и к TThread'y.

Автор: Гость_Vano 24.11.2003, 17:40
Поток делает цикл: (примерно 100 000 итераций)
...
for i:=1 to 100000 do
begin
x:=random(255);
sleep(1);
form1.repaint;
end;

.....
вешаю запуск Потока на кнопку на форме.
и как только я нажму кнопку.... я формой двигать не могу, сплошные тормоза,
все равно что выносить этот цикл в другой поток что не выносить.
подскажите как сделать чтобы я мог на форме спокойно работать, а поток пускай себе работает.

Автор: Ars 24.11.2003, 18:16
Убери form1.repaint; и все будет нормально. Окно и так перерисуется в случае надобности (ему винда сообщение пошлет)

Автор: Unregistered 28.11.2003, 16:41
Ars
form1.repaint; убрал все равно тормозит sad.gif

Автор: Ars 2.12.2003, 12:13
Цитата
form1.repaint; убрал все равно тормозит 

Странно... Посмотри в какой-нибудь проге мониторинга ресурсов (TaskInfo, например), сколько процессорного времени съедает твой поток.
Да, и можно попробовать Sleep(100). Если и после этого будет тормозить, то дело не в этом цикле.

Автор: Pushkin 2.12.2003, 19:26
он просто нагружает память, загружает на 95%, а от проц нифига не загружает (на 40% максимум)

Автор: Ars 3.12.2003, 17:57
Цитата
for i:=1 to 100000 do
begin
x:=random(255);
sleep(1);
form1.repaint;
end;

Цитата
он просто нагружает память, загружает на 95%, а от проц нифига не загружает (на 40% максимум)

Это не может загружать память.

Автор: pegu 22.2.2004, 01:18
приоритет в идле

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