Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.065 c
2-1339237885
Savek
2012-06-09 14:31
2013.03.22
Не удаётся сохранить картинку


2-1331146552
Delhessh
2012-03-07 22:55
2013.03.22
Одна процедура не видит другую!


15-1334134947
xss22
2012-04-11 13:02
2013.03.22
Утечки памяти в TStringList::GetText()


15-1341989915
AV
2012-07-11 10:58
2013.03.22
никто по SSH не соединялся? В частности, через cryptlib


15-1346830391
LDV
2012-09-05 11:33
2013.03.22
Delphi directory





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский