Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

Странное поведение потока   Найти похожие ветки 

 
leonidus ©   (2012-06-20 23:39) [0]

Создаю простой поток:

type
 Cheking_Thread = class(TThread)
 private
   { Private declarations }
   Nom:integer;
 protected
   procedure Execute; override;
 public
 end;

var
 Form1: TForm1;
 th:Cheking_Thread;

implementation

{$R *.dfm}

procedure Cheking_Thread.Execute;
begin
Nom:=Nom+1;
end;

Запускаю его предварительно инициализировав переменную Nom

procedure TForm1.Button1Click(Sender: TObject);
begin
th:=Cheking_Thread.Create(true);
th.Nom:=1;
th.FreeOnTerminate:=true;
th.Resume;
end;

Дожидаюсь отработки потока и его по идее самоуничтожения. После чего кликаю:
procedure TForm1.Button2Click(Sender: TObject);
begin
label1.Caption:=inttostr(th.nom);
end;

И к моему удивлению не получаю AV а получаю значение Nom равное 56. Откуда 56?? Почему вопреки заданному th.FreeOnTerminate:=true; поток жив?


 
jack128_   (2012-06-20 23:44) [1]


> И к моему удивлению не получаю AV

а с чего ты взял, что ты ОБЯЗАН получить AV ?? Ты МОЖЕШЬ его получить, но это не гарантированно. AV ты получишь только в том случае, если менеджер памяти отдаст кусок памяти, в которм сидел поток, обратно ОСи. Но на таком простом примере - это маловероятно.


 
Медвежонок Пятачок ©   (2012-06-20 23:45) [2]

1. поток мертв.
2. 56 из мусора


 
leonidus ©   (2012-06-20 23:58) [3]

да про 56 и мусор была догадка. Ок. Значит в общем случае обращение к переменной th возможно и после смерти потока.... суть проблемы в том, что запускается ряд экземпляров данного потока. В примере я посто упростил код. И основной поток ждет выполнения всех потоков в бесконечном цикле через Assigned проверяя живы потоки или нет. Когда потоки свое дело сделат и умрут основной поток должен узнать об этом. Но теперь получается, что Assigned(th) тоже не даст корректной инфы. что посоветуете?


 
Медвежонок Пятачок ©   (2012-06-21 00:02) [4]

зачем их проверять?
заняться нечем?
каждый запущенный поток перед смертью в состоянии оповестить кого надо о том, что его сейчас не станет.


 
Медвежонок Пятачок ©   (2012-06-21 00:21) [5]

Ветку надо назвать "странное поведение программиста".
Создаем поток,
говорим ему freeonterminate := true,
затем крутим бесконечный цикл чтобы узнать момент,
когда же наш поток уже помрет.


 
leonidus ©   (2012-06-21 00:37) [6]

Медвежонок Пятачок ваш сарказм оценил. Но давайте все же по теме. Пока писал придумал такой механизм. Запускаем скажем 10 потоков и и в глобальную переменную заносим "10". умирая каждый поток через критическую секцию уменьшает значение счетчика и заодно проверяет не является ли данный поток последний. Если он последний то последним оператором в теле потока будет вызов некой функции в основном потоке, извещая его о том, что все потоки умерли. Как считате так будет правильней?


 
Плохиш ©   (2012-06-21 00:38) [7]


> через Assigned проверяя живы потоки или нет.

Интересно, какое отношение Assigned имеет к жизни потоков?


 
Сергей М. ©   (2012-06-21 00:56) [8]


> leonidus ©   (21.06.12 00:37) [6]


Не нужно никаких крит.секций.

Класс TThread изначально уже заточен под упрощенное оповещение осн.потока о штатном терминировании своих инстанций. Заточка эта представлена событием OnTerminate - его обработчик вызывается в осн.потоке, извещая его о том что поток, представленный параметром Sender, закруглился по хозяйству и умрет в наикратчайшее время после возврата из обработчика.

Класс TThread к тому же виртуализирует защищенный метод DoTerminate, в контексте которого как раз и вызывается синхронизированное с осн.потоком событие OnTerminate. Достаточно перекрыть этот метод чтобы реализовать любую нестандартную логику "отчетности" потока о завершении.


 
Германн ©   (2012-06-21 02:22) [9]


> суть проблемы в том, что запускается ряд экземпляров данного
> потока. В примере я посто упростил код. И основной поток
> ждет выполнения всех потоков в бесконечном цикле через Assigned
> проверяя живы потоки или нет. Когда потоки свое дело сделат
> и умрут основной поток должен узнать об этом.

Опять задача XYZ.


 
Давайте будем жрать!   (2012-06-21 07:48) [10]

Неправда, «Z не предлагать!» в теме не звучало. А так — вполне логичный с точки зрения новичка подход: объект уничтожился, значит переменная должна стать nil.


 
Медвежонок Пятачок ©   (2012-06-21 11:01) [11]

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

ты просто чемпион по придумыванию хренотени.
мало того, что потоки сами себя считают, так они еще еще и знают (должны знать, что они не одиноки и сколько их там крутится вообще.

дружище, будь проще.
поток - единица кода. кирпичик. он должен уметь делать законченное полезное дело - раз, и он нихера не должен знать что он не один.

твой поток сейчас- это примерно как придумать кирпич (для строительства который), который сам проверяет, а не последний ли он в ряду.


 
AV ©   (2012-06-21 11:19) [12]

для простых задач стал практиковать так


> type
>  Cheking_Thread = class(TThread)
>  private
>    { Private declarations }
>    Nom:integer;
>  protected
>    procedure Execute; override;
>  public
CanKillMe: boolean;
>  end;


procedure Cheking_Thread.Execute;
begin
repeat
Nom:=Nom+1;
...
until Условие_окончания_работы;
CanKillMe := true;
end;

соответственно

> th.FreeOnTerminate:= false;


и потом либо просто
if th.CanKillMe then
begin
 Забираем у него результаты
 FreeAndNil(th);
end;

либо через тредмессадж поток пусть скажет сам, что он все, пора брать результат


 
Плохиш ©   (2012-06-21 11:32) [13]


>  объект уничтожился, значит переменная должна стать nil.

Какая из 100500 переменных?


 
Давайте будем жрать!   (2012-06-21 12:07) [14]


> Плохиш ©   (21.06.12 11:32) [13]
На то и новичок, что у него такого вопроса не возникает.


 
leonidus ©   (2012-06-21 12:56) [15]

Сергей М. спасибо за наводку. Сделал так.

procedure TForm1.Button1Click(Sender: TObject);
begin
th:=Cheking_Thread.Create(true);
th.Nom:=1;
th.OnTerminate=ThreadDone;
th.FreeOnTerminate:=true;
th.Resume;
end;

procedure TForm1.ThreadDone
begin
{тут каждый умирающий поток уменьшает значение глобальной переменной и как только ее значение становится равным 0 значи твсе потоки умерли и можно делать то что нужно}
end;


 
Anatoly Podgoretsky ©   (2012-06-21 13:30) [16]

> leonidus  (21.06.2012 12:56:15)  [15]

Тут вообще не нужна глобальная переменная.


 
Сергей М. ©   (2012-06-21 14:23) [17]


> как только ее значение становится равным 0 значи твсе потоки
> умерли


Не факт.
Минимум один доп.поток еще гарантированно живой.


 
leonidus ©   (2012-06-21 15:24) [18]

Удалено модератором
Примечание: Ну и не удивляйся


 
Сергей М. ©   (2012-06-21 15:40) [19]

Потоков много планируется к одновременной работе ?


 
leonidus ©   (2012-06-21 15:47) [20]

вплоть до 10


 
Сергей М. ©   (2012-06-21 15:48) [21]

ну тогда и заморачиваться не надо - делай как надумал в [15]


 
leonidus ©   (2012-06-21 15:51) [22]

спасибо!



Страницы: 1 вся ветка

Текущий архив: 2013.03.22;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.186 c
15-1329643520
AV
2012-02-19 13:25
2013.03.22
Посоветуйте что-нибудь, компонент не хочет работать в службе..


15-1340310602
Юрий
2012-06-22 00:30
2013.03.22
С днем рождения ! 22 июня 2012 пятница


15-1349295678
ProgRAMmer Dimonych
2012-10-04 00:21
2013.03.22
Подсчёт ссылок на строку таблицы в MySQL


15-1325340451
Pit
2011-12-31 18:07
2013.03.22
Delphi XE2 и крупные проекты


15-1339284234
alexdn
2012-06-10 03:23
2013.03.22
Ориентация планшетов