|
#1
|
|||
|
|||
Поток в потоке
есть некий поток дочерний. в главном он объявлен как массив
Код:
fNewTh: array [1..12]of Arr; Код:
i:= Length(fNewTh)+1; fNewTh[i]:=Arr.Create(); Последний раз редактировалось nixon232, 29.04.2017 в 12:52. |
#2
|
|||
|
|||
Получается, что поток (а наверное ссылка), остается в FNewTh[i]? потому что он не равен Nil?
Код:
for i := 1 to 12 do begin TMP:= fNewTh[i]; if not Assigned(tmp) then тогда где ему нил присвоить если мы не мониторим завершение экземпляра? |
#3
|
||||
|
||||
А и не должно значение само в nil сбрасывается. Делай это при завершении потока. Вариантов много.
Пишу программы за еду. __________________ |
#4
|
|||
|
|||
Цитата:
Код:
self:=nil; По дебагеру видно, что остались внутпеные даннык которые были созданы в Create Код:
begin inherited Create(False); a:=RBTN; b:= CBTN; c:=time; d:=id; FreeOnTerminate:=True; OnTerminate:=WBTerminate; end; Последний раз редактировалось nixon232, 30.04.2017 в 12:32. |
#5
|
|||
|
|||
Странно, но если в главном потоке послать такое, то ошибок нет и он оба раза шлет сигнал на поток
Код:
begin FreeAndNil(FLock); FBan.Free; for i := 1 to 12 do begin tmp:= fNewTh[i]; if tmp<>nil then tmp.Terminate; end; for i := 1 to 12 do begin tmp:= fNewTh[i]; if tmp<>nil then fNewTh[i].Terminate; end; inherited Destroy; end; Последний раз редактировалось nixon232, 30.04.2017 в 19:41. |
#6
|
|||
|
|||
переписал на Tlist Вместо Array of TA, а, в терминайте присваиваю
Код:
Self:=nil Код:
fNewTh.Add(TA.Create(....)); Код:
begin FreeAndNil(FLock); FBan.Free; begin // Cursor := crHourGlass; try if fNewTh.Count>0 then for i := fNewTh.Count - 1 downto 0 do begin if assigned(fNewTh[i]) then begin tmp:=fNewTh[i]; TA(fNewTh[i]).Terminate; // terminate thread TA(fNewTh[i]).WaitFor; // make sure thread terminates end; end; fNewTh.Clear; _____________________________АПД Если прописать так терминейт, то ошибки нет, но во-первых это бред так делать, а во-вторых объект-то остался. Код:
procedure TA.Terminate(Sender : TObject); begin //Self:=nil; MainThread.fNewTh.Delete(fIndex); end; Последний раз редактировалось nixon232, 01.05.2017 в 14:42. |
#7
|
||||
|
||||
Поток делфи - TThread - это объект (кусок памяти), с которым ассоциирована внутренняя структура ОС под названием "поток".
В массиве (который в данном случае вообще непонятно зачем существует, если используется только один поток) хранится указатель на этот объект, то есть просто адрес ("номер") объекта (куска памяти). Если снести жилой дом, его адрес же не исчезнет сам из всех справочников, верно? Точно так же и указатель на удаленный объект (адрес куска памяти) сам не исчезнет ниоткуда, пока ты руками не удалишь его. Сохранял его в переменной - он останется в переменной. Сохранял в массиве - он останется в массиве. Поэтому, очевидно, если указатель на поток должен удаляться из какой-то коллекции (в данном случае - массива), нужно в момент удаления объекта TThread убирать указатель на него самому. NumLock об этом уже написал. А Self в методе потока Terminate - просто еще одна копия адреса этого объекта. От её зануления ничего во внешнем массиве не изменится. jmp $ ; Happy End! The Cake Is A Lie. |
#8
|
|||
|
|||
Цитата:
Кратко цель: главный поток нечто ищет, когда нашел, создал доч-поток, который отсчитал время( условно) - удалил это нечто и удалился сам. Если таких объектов много, то и время считается независимо. То есть главное, чтобы во время счета продолжался поиск. Последний раз редактировалось nixon232, 01.05.2017 в 16:14. |
#9
|
||||
|
||||
На мой взгляд для этих целей проще использовать обычный таймер.
Поиск запустить в одном отдельном потоке, и оттуда ставить таймер, указав обработчик. Через synchronize, разумеется. По истечение таймаута в главном потоке вызовется обработчик, который сделает всё, что нужно. Ну или создавать делфийский объект "таймер", ставить ему значение и обработчик, и по завершении удалять его. Или - проще, но не особо точно по времени: при "нахождении" чего-то добавить в список структуру, содержащую то, что надо удалить, и таймаут. Далее просто по повторяющемуся таймеру Delphi каждую условно секунду вычитать 1 из таймаутов всех элементов списка, а когда значение элемента достигло нуля - удалять. Ну и обмазать всё это синзронизацией, разумеется. Почему эти два подхода лучше - главный поток не висит, а значит - приложение не "зависает". Ну и не плодятся бесполезные потоки, которые только и делают, что Sleep. jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 01.05.2017 в 16:36. |
Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
nixon232 (01.05.2017)
|
#10
|
|||
|
|||
Уже не буду созвать новую тему. Разве нельзя объявить такое в потоке? при попытке сделать SetTimer, События нет
Код:
TA= class(TThread) private ..... procedure WMTimer( var Msg: TWMTimer ); message WM_TIMER; |
#11
|
||||
|
||||
Я же специально написал:
Цитата:
jmp $ ; Happy End! The Cake Is A Lie. |
Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
nixon232 (01.05.2017)
|
#12
|
|||
|
|||
Распишу тогда, что в итоге сделал и за одно скажите, насколько так безопасно.
Создаем таймер в потоке поиска, если нашлии Код:
SetTimer(MForm.Handle,.ID,fTime,nil); В момент таймера Меняем пропети потока и передаем элемент, который "отсчитался": Код:
procedure TMForm.WMTimer(var Msg: TWMTimer); begin Search.OnTimeElemt:=Msg.TimerID; Search.OnTime:=True; Msg.Result:=0; //KillTimer(Handle,Msg.TimerID); inherited end; Код:
procedure TFindeer.SetOnTime(const Value: Boolean); begin if fOnTime <> Value then fOnTime := Value; if fOnTime then Synchronize(Kill); end; procedure TFindeer.kill; begin {here kill some object and killtimmer} //сброс флагов fONTime:=False; fElement:=-1; |
#13
|
||||
|
||||
На форме 5 меток и кнопка. При нажатии на кнопку стартует поток с незанятой меткой. После завершения потока метка снова освобождается.
Код:
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TMyThread = class(TThread) protected procedure Execute; override; public FLabel: TLabel; constructor Create(ALabel: TLabel); overload; end; TForm1 = class(TForm) Button1: TButton; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } procedure ThreadTerminate(Sender: TObject); public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} { TMyThread } constructor TMyThread.Create(ALabel: TLabel); begin FLabel:=ALabel; FreeOnTerminate:=True; inherited Create(False); end; procedure TMyThread.Execute; var TickCount: Integer; begin TickCount:=Random(10)+1; Synchronize(procedure begin FLabel.Caption:=IntToStr(TickCount); end); (* do it *) while TickCount>0 do begin Synchronize(procedure begin FLabel.Caption:=IntToStr(TickCount); end); Dec(TickCount); Sleep(1000); end; Synchronize(procedure begin FLabel.Tag:=0; FLabel.Caption:='stoped'; end); end; { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin Randomize; end; procedure TForm1.Button1Click(Sender: TObject); var i: Integer; lbl: TLabel; rslt: Boolean; begin rslt:=False; for i:=1 to 5 do begin lbl:=TLabel(FindComponent('Label'+IntToStr(i))); if lbl.Tag=0 then begin lbl.Tag:=$7FFFFFFF; Button1.Tag:=Button1.Tag+1; Button1.Caption:=IntToStr(Button1.Tag); with TMyThread.Create(lbl) do OnTerminate:=ThreadTerminate; rslt:=True; Break; end; end; if not rslt then ShowMessage('Oops'); end; procedure TForm1.ThreadTerminate(Sender: TObject); begin Button1.Tag:=Button1.Tag-1; Button1.Caption:=IntToStr(Button1.Tag); end; end. Пишу программы за еду. __________________ |
Этот пользователь сказал Спасибо NumLock за это полезное сообщение: | ||
nixon232 (02.05.2017)
|
#14
|
|||
|
|||
Спасибо, на досуге изучу
|
#15
|
||||
|
||||
Цитата:
Цитата:
jmp $ ; Happy End! The Cake Is A Lie. |
Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
nixon232 (14.05.2017)
|