Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 29.04.2017, 10:51
nixon232 nixon232 вне форума
Активный
 
Регистрация: 26.01.2014
Сообщения: 282
Версия Delphi: delphi xe4
Репутация: выкл
По умолчанию Поток в потоке

есть некий поток дочерний. в главном он объявлен как массив
Код:
fNewTh: array [1..12]of Arr;
По отработке (как я думал) они освобождаются, но как мне создать новый экземпляр потока на месте отработанного, а не забивать новый элемент массива?
Код:
i:= Length(fNewTh)+1;
   fNewTh[i]:=Arr.Create();
но оно. очевидно вернет 13. а не индекс заполненных элементов.

Последний раз редактировалось nixon232, 29.04.2017 в 12:52.
Ответить с цитированием
  #2  
Старый 29.04.2017, 17:16
nixon232 nixon232 вне форума
Активный
 
Регистрация: 26.01.2014
Сообщения: 282
Версия Delphi: delphi xe4
Репутация: выкл
По умолчанию

Получается, что поток (а наверное ссылка), остается в FNewTh[i]? потому что он не равен Nil?
Код:
for i := 1 to 12 do
    begin
    TMP:= fNewTh[i];
      if not Assigned(tmp) then

тогда где ему нил присвоить если мы не мониторим завершение экземпляра?
Ответить с цитированием
  #3  
Старый 30.04.2017, 06:05
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

А и не должно значение само в nil сбрасывается. Делай это при завершении потока. Вариантов много.
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #4  
Старый 30.04.2017, 12:29
nixon232 nixon232 вне форума
Активный
 
Регистрация: 26.01.2014
Сообщения: 282
Версия Delphi: delphi xe4
Репутация: выкл
По умолчанию

Цитата:
Сообщение от NumLock
А и не должно значение само в nil сбрасывается. Делай это при завершении потока. Вариантов много.
ну мне хватит и одно. пробовал в терминейт дочернего объекта прописать
Код:
self:=nil;
Но Assigned дает true.
По дебагеру видно, что остались внутпеные даннык которые были созданы в 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  
Старый 30.04.2017, 19:36
nixon232 nixon232 вне форума
Активный
 
Регистрация: 26.01.2014
Сообщения: 282
Версия Delphi: delphi xe4
Репутация: выкл
По умолчанию

Странно, но если в главном потоке послать такое, то ошибок нет и он оба раза шлет сигнал на поток
Код:
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;
в самом потоке уже осталось Sleep(1000); и все. получается он не завершается? но ведь доходит до Destroy.

Последний раз редактировалось nixon232, 30.04.2017 в 19:41.
Ответить с цитированием
  #6  
Старый 01.05.2017, 14:20
nixon232 nixon232 вне форума
Активный
 
Регистрация: 26.01.2014
Сообщения: 282
Версия Delphi: delphi xe4
Репутация: выкл
По умолчанию

переписал на Tlist Вместо Array of TA, а, в терминайте присваиваю
Код:
 Self:=nil
Создаю поток:
Код:
       fNewTh.Add(TA.Create(....));
Он себе спокойно отрабатывает, доходит до дестроя, но при такой проверке пытается уничтожить объект, которого нет, получает отказв доступе код 5 и вылетает
Код:
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  
Старый 01.05.2017, 15:26
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Поток делфи - TThread - это объект (кусок памяти), с которым ассоциирована внутренняя структура ОС под названием "поток".
В массиве (который в данном случае вообще непонятно зачем существует, если используется только один поток) хранится указатель на этот объект, то есть просто адрес ("номер") объекта (куска памяти).

Если снести жилой дом, его адрес же не исчезнет сам из всех справочников, верно? Точно так же и указатель на удаленный объект (адрес куска памяти) сам не исчезнет ниоткуда, пока ты руками не удалишь его. Сохранял его в переменной - он останется в переменной. Сохранял в массиве - он останется в массиве.
Поэтому, очевидно, если указатель на поток должен удаляться из какой-то коллекции (в данном случае - массива), нужно в момент удаления объекта TThread убирать указатель на него самому. NumLock об этом уже написал.
А Self в методе потока Terminate - просто еще одна копия адреса этого объекта. От её зануления ничего во внешнем массиве не изменится.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #8  
Старый 01.05.2017, 16:09
nixon232 nixon232 вне форума
Активный
 
Регистрация: 26.01.2014
Сообщения: 282
Версия Delphi: delphi xe4
Репутация: выкл
По умолчанию

Цитата:
Сообщение от Bargest
Поток делфи - TThread - это объект (кусок памяти), с которым ассоциирована внутренняя структура ОС под названием "поток".
В массиве (который в данном случае вообще непонятно зачем существует, если используется только один поток) хранится указатель на этот объект, то есть просто адрес ("номер") объекта (куска памяти).

Если снести жилой дом, его адрес же не исчезнет сам из всех справочников, верно? Точно так же и указатель на удаленный объект (адрес куска памяти) сам не исчезнет ниоткуда, пока ты руками не удалишь его. Сохранял его в переменной - он останется в переменной. Сохранял в массиве - он останется в массиве.
Поэтому, очевидно, если указатель на поток должен удаляться из какой-то коллекции (в данном случае - массива), нужно в момент удаления объекта TThread убирать указатель на него самому. NumLock об этом уже написал.
А Self в методе потока Terminate - просто еще одна копия адреса этого объекта. От её зануления ничего во внешнем массиве не изменится.
Тогда как мне сделать нужную мне вещь? Ведь если написать WaitFor, то встанет главный поток и потеряется весь смысл в дочернем потоке.

Кратко цель: главный поток нечто ищет, когда нашел, создал доч-поток, который отсчитал время( условно) - удалил это нечто и удалился сам. Если таких объектов много, то и время считается независимо.
То есть главное, чтобы во время счета продолжался поиск.

Последний раз редактировалось nixon232, 01.05.2017 в 16:14.
Ответить с цитированием
  #9  
Старый 01.05.2017, 16:23
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

На мой взгляд для этих целей проще использовать обычный таймер.
Поиск запустить в одном отдельном потоке, и оттуда ставить таймер, указав обработчик. Через synchronize, разумеется. По истечение таймаута в главном потоке вызовется обработчик, который сделает всё, что нужно.
Ну или создавать делфийский объект "таймер", ставить ему значение и обработчик, и по завершении удалять его.

Или - проще, но не особо точно по времени: при "нахождении" чего-то добавить в список структуру, содержащую то, что надо удалить, и таймаут. Далее просто по повторяющемуся таймеру Delphi каждую условно секунду вычитать 1 из таймаутов всех элементов списка, а когда значение элемента достигло нуля - удалять. Ну и обмазать всё это синзронизацией, разумеется.

Почему эти два подхода лучше - главный поток не висит, а значит - приложение не "зависает". Ну и не плодятся бесполезные потоки, которые только и делают, что Sleep.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.

Последний раз редактировалось Bargest, 01.05.2017 в 16:36.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
nixon232 (01.05.2017)
  #10  
Старый 01.05.2017, 22:53
nixon232 nixon232 вне форума
Активный
 
Регистрация: 26.01.2014
Сообщения: 282
Версия Delphi: delphi xe4
Репутация: выкл
По умолчанию

Уже не буду созвать новую тему. Разве нельзя объявить такое в потоке? при попытке сделать SetTimer, События нет
Код:
TA= class(TThread)
  private
 .....
    procedure WMTimer( var Msg: TWMTimer ); message WM_TIMER;
Ответить с цитированием
  #11  
Старый 01.05.2017, 23:18
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Я же специально написал:
Цитата:
Через synchronize, разумеется. По истечение таймаута в главном потоке вызовется обработчик
Потому что таймер ассоциирован с окном, а окно принадлежит главному потоку.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
nixon232 (01.05.2017)
  #12  
Старый 02.05.2017, 09:30
nixon232 nixon232 вне форума
Активный
 
Регистрация: 26.01.2014
Сообщения: 282
Версия Delphi: delphi xe4
Репутация: выкл
По умолчанию

Распишу тогда, что в итоге сделал и за одно скажите, насколько так безопасно.
Создаем таймер в потоке поиска, если нашлии
Код:
      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  
Старый 02.05.2017, 13:56
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

На форме 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.
Вложения
Тип файла: zip MyThread.zip (57.4 Кбайт, 0 просмотров)
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
nixon232 (02.05.2017)
  #14  
Старый 02.05.2017, 14:51
nixon232 nixon232 вне форума
Активный
 
Регистрация: 26.01.2014
Сообщения: 282
Версия Delphi: delphi xe4
Репутация: выкл
По умолчанию

Спасибо, на досуге изучу
Ответить с цитированием
  #15  
Старый 05.05.2017, 01:39
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Цитата:
В момент таймера Меняем пропети потока и передаем элемент, который "отсчитался":
Не очень здорово. Два таймера могут отработать прямо подряд, и результат одного из них потеряется. Поэтому
Цитата:
{here kill some object and killtimmer}
лучше выполнять прямо из главного потока по сообщению таймера.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
nixon232 (14.05.2017)
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 17:06.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter