![]() |
|
|
#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 - просто еще одна копия адреса этого объекта. От её зануления ничего во внешнем массиве не изменится. |
|
#8
|
|||
|
|||
|
Цитата:
Кратко цель: главный поток нечто ищет, когда нашел, создал доч-поток, который отсчитал время( условно) - удалил это нечто и удалился сам. Если таких объектов много, то и время считается независимо. То есть главное, чтобы во время счета продолжался поиск. Последний раз редактировалось nixon232, 01.05.2017 в 16:14. |
|
#9
|
||||
|
||||
|
На мой взгляд для этих целей проще использовать обычный таймер.
Поиск запустить в одном отдельном потоке, и оттуда ставить таймер, указав обработчик. Через synchronize, разумеется. По истечение таймаута в главном потоке вызовется обработчик, который сделает всё, что нужно. Ну или создавать делфийский объект "таймер", ставить ему значение и обработчик, и по завершении удалять его. Или - проще, но не особо точно по времени: при "нахождении" чего-то добавить в список структуру, содержащую то, что надо удалить, и таймаут. Далее просто по повторяющемуся таймеру Delphi каждую условно секунду вычитать 1 из таймаутов всех элементов списка, а когда значение элемента достигло нуля - удалять. Ну и обмазать всё это синзронизацией, разумеется. Почему эти два подхода лучше - главный поток не висит, а значит - приложение не "зависает". Ну и не плодятся бесполезные потоки, которые только и делают, что Sleep. Последний раз редактировалось 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
|
||||
|
||||
|
Я же специально написал:
Цитата:
|
| Этот пользователь сказал Спасибо 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
|
||||
|
||||
|
Цитата:
Цитата:
|
| Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
nixon232 (14.05.2017)
| ||