Создание объекта с полем Thread с функцией Execute из текущего класса

HOME_X
Дата: 06.07.2019 11:36:35
Доброго дня господа !

Первопричина темы - невозможно запустить Thread дважды без пересоздания объекта
1. a:=Thread.Create(....)
2. a.Resume
3. Поток нормально отработал
4. a.Resume запустить еще раз невозможно
У меня на Create висят ряд функций, которые нежелательно выполнять многократно
Если ошибаюсь в выводах прошу поправить/подсказать ....


Как решение вижу создать класс у которого одно из полей будет Thread, но не знаю
как присвоить/установить функцию Thread.Execute взяв ее из текущего класса
Т.е.
     AAA = class(TObject)
         ...........................
         ...........................        
     public 
         B: Thread;
         procudure  ExecuteMyObject; 

     constructor AAA.Create((..............)
     begin 
         B:=Thread.Create(False);
         B.Execute :=  ExecuteMyObject;   ????????????
        ///Здесь не понимаю как пойдет процесс присвоения и дальнейшей вызов. 
     end;

     procudure  ExecuteMyObject; 
     begin 
        /// основной функционал для выполнения в потоке ... 
     end;


Заранее благодарен !
makhaon
Дата: 06.07.2019 13:02:32
HOME_X,

поток работает от начала execute до конца execute. соответственно, если нужно что бы один и тот же поток отрабатывал несколько раз какой-то код в execute нужно сделать цикл. другой вариант - создать несколько экземпляров TYourThread, смотря что нужно
HOME_X
Дата: 06.07.2019 13:42:09
makhaon,

Надо так - ввел параметры - отработал поток
- ввел другие параметры - отработал тот же поток c введенными параметрами

Цикл не подходит однозначно, сейчас я имею многократное пересоздание потоков

Можете что-то сказать относительно
поля Thread нового класса - как присвоить Execute ?
krapotkin
Дата: 06.07.2019 14:06:54
Вполне нормально создавать потоки заново.
Это одна из основных задач ОС, так что потоки - относительно дешево.
Дорогим может быть само создание класса потока, но и там нет ничего такого, чем программа не занимается непрерывно, и для оптимизации вполне подходят общепринятые методы.
krapotkin
Дата: 06.07.2019 14:08:48
Без понимания, что конкретно вы имели в виду, говоря про "ряд функций" в Create, подсказать ничего невозможно. Потому что сейчас мы имеем классику XYZ по GunSmoker ))
HOME_X
Дата: 06.07.2019 15:04:08
krapotkin
Без понимания, что конкретно вы имели в виду, говоря про "ряд функций" в Create, подсказать ничего невозможно. Потому что сейчас мы имеем классику XYZ по GunSmoker ))


Тут понимание такое что есть ряд операций, которые выполняются единоразово, и в их дублировании просто нет
логического смысла(ну например настройка приложения по NLS стандартам и т.д.)

Попытался сделать так - не знаю верно ли !!!
Уточните господа гуру - верно ли ПРИСВОИЛ метод Execute для потока

type
  TAddSpan = class;

  TAddExec = class(TThread)   //поле основного объекта
  private
    Parent: TAddSpan;
  protected
    //
  public
    constructor Create(aParent: TAddSpan);
    procedure   Execute; override;
  published
    //
  end;

  TAddSpan = class(TObject)   
  private
    thExec:   TAddExec;
 protected
    //
 public
    ......................
    procedure   ExecuteThread;
    procedure   ExecuteParent;
  published
    //
  end;

implementation

uses Main;

  constructor TAddExec.Create(aParent: TAddSpan);
  begin
    Parent:=aParent;
    Inherited Create(True);
  end;

  procedure TAddExec.Execute;
  begin
    Parent.ExecuteParent;
  end;


  procedure TAddSpan.ExecuteThread;
  begin
    thExec:=TAddExec.Create(Self);
    thExec.Resume;
  end;

  procedure TAddSpan.ExecuteParent;
  var I: Integer;
      L: TStringList;
  begin
    L:=TStringList.Create;
    for i:=1 to 20000000 do begin
      L.Add('Row '+IntToStr(I));
    end;
    L.SaveToFile('C:\WORK\rr12.txt');
    L.Free;
  end;


Так вроде все работает ....
x1ca4064
Дата: 06.07.2019 19:11:01
HOME_X
Цикл не подходит однозначно, сейчас я имею многократное пересоздание потоков

Можете что-то сказать относительно
поля Thread нового класса - как присвоить Execute ?


Цикл отлично подходит - просто его надо правильно написать (примерный код):
type
  TTaskProc=procedure (Self:TWrkThread;Param:pointer);
  TTaskProcObj=procedure (Self:TWrkThread;Param:pointer) of object;

procedure TWrkThread.Execute;
while not Terminated do
begin
  if WakeUpEvent.WaitFor then
  begin
    if Terminated then exit;
    if TaskProc<>nil then 
    begin
      TaskProc(Self,Param);
      TaskProc:=nil;
    end;
    If TaskProcObj<>nil then
    begin
      TaskProcObj(Self,Param);
      TaskProcObj:=nil;
    end;
  end;
end;


Работает так: Устанавливаем WrkThread.TaskProc (или TaskProcObj) , далее WrkThread.WakeUpEvent.SetEvent - процедура, которую задали в TaskProc выполняется в потоке, поток выполняет заданное и возвращается в состояние ожидания.
x1ca4064
Дата: 06.07.2019 19:13:49
HOME_X,
Чуть ошибся в декларации:
type
  TTaskProc=procedure (Sender:TWrkThread;Param:pointer);
  TTaskProcObj=procedure (Sender:TWrkThread;Param:pointer) of object;
X-Cite
Дата: 06.07.2019 21:36:09
Вам нужен поток, чтобы в нем делать определенные вещи - постоянно или продолжительно долго..
Или вам время от времени надо выполнять асинхронные задачи?
HOME_X
Дата: 06.07.2019 21:54:50
x1ca4064
HOME_X,
Чуть ошибся в декларации:
type
  TTaskProc=procedure (Sender:TWrkThread;Param:pointer);
  TTaskProcObj=procedure (Sender:TWrkThread;Param:pointer) of object;



Чуток подправил - неопределенный класс первичного кода
(TAddSpan = class;) совсем не к месту, просто ссылка на метод объекта

type
  TMethod  = procedure of object;

  TAddExec = class(TThread)
  private
    ParentExecute: TMethod;
  protected
    //
  public
    constructor Create(aMethod: TMethod);
    procedure   Execute; override;
  published
    //
  end;


implementation

uses Main;

  constructor TAddExec.Create(aMethod: TMethod);
  begin
    Inherited Create(True);
    ParentExecute:=aMethod;
    FreeOnTerminate:=True;
    OnTerminate:=frMain.TerminateThread;
  end;

  procedure TAddExec.Execute;
  begin
    ParentExecute;
  end;

 ..................
 ..................
 ..................
 ..................

  procedure TAddSpan.ExecuteThread;
  begin
    thExec:=TAddExec.Create(Self.Execute);
    thExec.Resume;
  end;


Цикл не нужен ...запуск потока эпизодический, по требованию пользователя