![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Странное поведение потока [D6, WinXP]
leonidus © (2012-06-20 23:39:00)Создаю простой поток:
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; поток жив?
leonidus (2012-06-21 15:51:00) [1]спасибо!
Сергей М. (2012-06-21 15:48:00) [2]ну тогда и заморачиваться не надо - делай как надумал в [15]
leonidus (2012-06-21 15:47:00) [3]вплоть до 10
Сергей М. (2012-06-21 15:40:00) [4]Потоков много планируется к одновременной работе ?
leonidus (2012-06-21 15:24:00) [5]Удалено модератором
Примечание: Ну и не удивляйся
Сергей М. (2012-06-21 14:23:00) [6]
> как только ее значение становится равным 0 значи твсе потоки
> умерли
Не факт.
Минимум один доп.поток еще гарантированно живой.
Anatoly Podgoretsky (2012-06-21 13:30:00) [7]> leonidus (21.06.2012 12:56:15) [15]
Тут вообще не нужна глобальная переменная.
leonidus (2012-06-21 12:56:00) [8]Сергей М. спасибо за наводку. Сделал так.
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;
Давайте будем жрать! (2012-06-21 12:07:00) [9]
> Плохиш © (21.06.12 11:32) [13]
На то и новичок, что у него такого вопроса не возникает.
Плохиш (2012-06-21 11:32:00) [10]
> объект уничтожился, значит переменная должна стать nil.
Какая из 100500 переменных?
AV (2012-06-21 11:19:00) [11]для простых задач стал практиковать так
> 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:01:00) [12]Пока писал придумал такой механизм. Запускаем скажем 10 потоков и и в глобальную переменную заносим "10". умирая каждый поток через критическую секцию уменьшает значение счетчика и заодно проверяет не является ли данный поток последний.
ты просто чемпион по придумыванию хренотени.
мало того, что потоки сами себя считают, так они еще еще и знают (должны знать, что они не одиноки и сколько их там крутится вообще.
дружище, будь проще.
поток - единица кода. кирпичик. он должен уметь делать законченное полезное дело - раз, и он нихера не должен знать что он не один.
твой поток сейчас- это примерно как придумать кирпич (для строительства который), который сам проверяет, а не последний ли он в ряду.
Давайте будем жрать! (2012-06-21 07:48:00) [13]Неправда, «Z не предлагать!» в теме не звучало. А так — вполне логичный с точки зрения новичка подход: объект уничтожился, значит переменная должна стать nil.
Германн (2012-06-21 02:22:00) [14]
> суть проблемы в том, что запускается ряд экземпляров данного
> потока. В примере я посто упростил код. И основной поток
> ждет выполнения всех потоков в бесконечном цикле через Assigned
> проверяя живы потоки или нет. Когда потоки свое дело сделат
> и умрут основной поток должен узнать об этом.
Опять задача XYZ.
Сергей М. (2012-06-21 00:56:00) [15]
> leonidus © (21.06.12 00:37) [6]
Не нужно никаких крит.секций.
Класс TThread изначально уже заточен под упрощенное оповещение осн.потока о штатном терминировании своих инстанций. Заточка эта представлена событием OnTerminate - его обработчик вызывается в осн.потоке, извещая его о том что поток, представленный параметром Sender, закруглился по хозяйству и умрет в наикратчайшее время после возврата из обработчика.
Класс TThread к тому же виртуализирует защищенный метод DoTerminate, в контексте которого как раз и вызывается синхронизированное с осн.потоком событие OnTerminate. Достаточно перекрыть этот метод чтобы реализовать любую нестандартную логику "отчетности" потока о завершении.
Плохиш (2012-06-21 00:38:00) [16]
> через Assigned проверяя живы потоки или нет.
Интересно, какое отношение Assigned имеет к жизни потоков?
leonidus (2012-06-21 00:37:00) [17]Медвежонок Пятачок ваш сарказм оценил. Но давайте все же по теме. Пока писал придумал такой механизм. Запускаем скажем 10 потоков и и в глобальную переменную заносим "10". умирая каждый поток через критическую секцию уменьшает значение счетчика и заодно проверяет не является ли данный поток последний. Если он последний то последним оператором в теле потока будет вызов некой функции в основном потоке, извещая его о том, что все потоки умерли. Как считате так будет правильней?
Медвежонок Пятачок (2012-06-21 00:21:00) [18]Ветку надо назвать "странное поведение программиста".
Создаем поток,
говорим ему freeonterminate := true,
затем крутим бесконечный цикл чтобы узнать момент,
когда же наш поток уже помрет.
Медвежонок Пятачок (2012-06-21 00:02:00) [19]зачем их проверять?
заняться нечем?
каждый запущенный поток перед смертью в состоянии оповестить кого надо о том, что его сейчас не станет.
leonidus (2012-06-20 23:58:00) [20]да про 56 и мусор была догадка. Ок. Значит в общем случае обращение к переменной th возможно и после смерти потока.... суть проблемы в том, что запускается ряд экземпляров данного потока. В примере я посто упростил код. И основной поток ждет выполнения всех потоков в бесконечном цикле через Assigned проверяя живы потоки или нет. Когда потоки свое дело сделат и умрут основной поток должен узнать об этом. Но теперь получается, что Assigned(th) тоже не даст корректной инфы. что посоветуете?