Форум: "Начинающим";
Текущий архив: 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.074 c