Конференция "Начинающим" » потоки(TThread) и свойства(property), не все понятно
 
  • Pcrepair © (04.06.18 19:33) [0]
    Добрый день. Есть следующий демокод:

    unit uNewThread;
    interface
    uses
     System.Classes,SysUtils,Dialogs,SyncObjs,StrUtils,ExtCtrls,Windows,
     WideStrUtils,Vcl.Forms;

     procedure  ThreadDoJob(const aHost:string; var aErrorMsg:string; var aIsJobDone:Boolean);

    type
     DoJob = class(TThread)
     private
       fHost,fErrorMsg:string;
       fIsJobDone:Boolean;
     protected
       procedure Execute; override;
     public
       property ErrorMsg:string read fErrorMsg;
       property IsJobDone:Boolean read fIsJobDone;

       constructor Create(const aHost:string; var aErrorMsg:string; var aIsJobDone:Boolean);
       destructor Destroy; override;
     end;

    implementation

    procedure  ThreadDoJob(const aHost:string; var aErrorMsg:string; var aIsJobDone:Boolean);
    var
     ThreadJob:DoJob;
    begin
     ThreadJob:=DoJob.Create(aHost,aErrorMsg,aIsJobDone);
     aErrorMsg:=ThreadJob.ErrorMsg;
     aIsJobDone:=ThreadJob.IsJobDone;
    end;

    constructor DoJob.Create(const aHost:string; var aErrorMsg:string; var aIsJobDone:Boolean);
    begin
     inherited Create(False);
     FreeOnTerminate := True;
     Self.Priority := tpLower;
     fHost:=aHost;
    end;

    destructor DoJob.Destroy;
    begin
     inherited Destroy;
    end;

    procedure DoJob.Execute;
    var
     flg:Boolean;
    begin
     flg:=true;  (*or FALSE just for fun*)

     if flg then
     begin
       fIsJobDone:=TRUE;
       fErrorMsg:='7777';
     end
     else
     begin
       fIsJobDone:=FALSE;
       fErrorMsg:='6666';
     end;

    end.



    прогнозируемо aErrorMsg:=ThreadJob.ErrorMsg; и aIsMailSended:=ThreadJob.IsMailSended; выводят "ничего" в выше стоящий код

    Вопрос : как вывести результат работы потока в обработчики но без "Synchronize", трубы и прочего из той же оперы а через "property". если такое для потока вообще возможно. что то читал про OnTerminate но ничего канкретно применительно к "property" не нашлось.
  • icp © (04.06.18 22:18) [1]
    при таком дизайне поток не нужен.
    свойство если читать то оно возвращает значение. без разницы что это за класс.
  • icp © (04.06.18 22:27) [2]
    не "выводят" потому что там ничего нет.
    а ничего нет потому что не присвоено.
    дальше.
    если ты планируешь создать поток и в след
    строчке читать значение
    то зачем тебе вообще поток.
    переси код в экзекута в другую процедуру и не в потоке.
    будет все тоже самое.
  • icp © (04.06.18 22:38) [3]
    ах да.
    там еще и фрионтерминате.
    просто интересно.
    как ты собрался ловить ту наносекунду когда результат уже готов но поток еще не успел самовыпилиться?
  • Pcrepair © (04.06.18 22:44) [4]
    этот и есть мой вопрос - как
  • KSergey © (05.06.18 06:18) [5]
    > Вопрос : как вывести результат работы потока в обработчики
    > но без "Synchronize", трубы и прочего из той же оперы а через "property".

    Надо дождаться окончания работы потока (т.е. окончания выполнения DoJob.Execute) и после этого прочитать property
  • icp © (05.06.18 06:45) [6]
    тока после экзекута никакого свойства уже нет как и самого потока.
    к тому же дождаться это эквивалентно тому когда екзекут выполняется в основном потоке
  • KSergey © (05.06.18 08:12) [7]
    > icp ©   (05.06.18 06:45) [6]
    > тока после экзекута никакого свойства уже нет как и самого  потока.

    Чего это вдруг?
    Потока (операционной системы) конечно нет, а Delphi-объект - куда ж он делся? на месте он. Можно читать/писать свойства без проблем.

    > к тому же дождаться это эквивалентно тому когда екзекут выполняется в основном потоке

    "Ждать" не эквивалентно "стоять и ждать".
    Можно заниматься чем-то полезным, проверяя периодически не завершился ли поток.
    Ну или не проверять, а как-то иначе просигнализировать основному потоку "я выполнился" (сообщение через PostMEssage в главную форму кинуть хотя бы, например, как самое простое)
  • icp © (05.06.18 08:14) [8]
    с таво вдруг что фрионтерминэйт.
    екзекут завершился и кирдык всему экземпляру настает
  • icp © (05.06.18 08:15) [9]
    сказано же по русски.
    что в таком дизайне поток здесь нафик не нужен.
  • KSergey © (05.06.18 08:18) [10]
    > Pcrepair ©   (04.06.18 19:33) 

    Кстати, вставьте вот такую простую штуку - и, думаю, свойства у вас сразу прочитаются.

    procedure  ThreadDoJob(const aHost:string; var aErrorMsg:
    string; var aIsJobDone:Boolean);
    var
     ThreadJob:DoJob;
    begin
     ThreadJob:=DoJob.Create(aHost,aErrorMsg,aIsJobDone);
     Sleep(0);
     aErrorMsg:=ThreadJob.ErrorMsg;
     aIsJobDone:=ThreadJob.IsJobDone;
    end;
  • KSergey © (05.06.18 08:19) [11]
    > icp ©   (05.06.18 08:14) [8]
    > с таво вдруг что фрионтерминэйт.

    Да, не заметил, извиняюсь.
    Его убрать, конечно, смысла с него нет, тем более в данном случае.
  • KSergey © (05.06.18 08:20) [12]
    > icp ©   (05.06.18 08:15) [9]
    > сказано же по русски.
    > что в таком дизайне поток здесь нафик не нужен.

    Ясно же, что пример крайне демонтрационый
    как раз для понимания всех этих моментов
  • icp © (05.06.18 08:22) [13]
    вот для понимания я и сказал ему.
    что если делать как он хочет то не надо лепить поток.
    ибо смысла ноль
  • Leonid Troyanovsky © (05.06.18 08:28) [14]

    > icp ©   (05.06.18 08:14) [8]

    > екзекут завершился и кирдык всему экземпляру настает

    Сначала выполнится онтерминэйт  в первичном потоке,
    а уж потом "екзекут завершился и кирдык всему".

    --
    Regards, LVT.
  • icp © (05.06.18 08:51) [15]
    да да.
    остается только поймать этот миг.
    когда уже готово но все еще живо.
    без извратов то неможно
  • Leonid Troyanovsky © (05.06.18 09:13) [16]

    > icp ©   (05.06.18 08:51) [15]

    > остается только поймать этот миг.
    > когда уже готово но все еще живо.

    Я ж и говорю, что в OnTerminate этих мгновений м.б. хоть 17.

    --
    Regards, LVT.
  • Leonid Troyanovsky © (05.06.18 09:19) [17]

    > icp ©   (05.06.18 08:22) [13]

    > что если делать как он хочет то не надо лепить поток

    Видимо, он хочет Fire & Forget.
    Ненаказуемо.

    --
    Regards, LVT.
  • icp © (05.06.18 09:32) [18]
    какой же тут форгет если он паблик проперти придумал.
    здесь ремембер ол лайф тайм
  • Pcrepair © (05.06.18 09:39) [19]
    подкину дровишек. вот так демо работает. несмотря на выше опубликованный базар

    unit uNewThread;
    interface
    uses
     System.Classes,SysUtils,Dialogs,SyncObjs,StrUtils,ExtCtrls,Windows,
     WideStrUtils,Vcl.Forms;

     procedure  ThreadDoJob(const aHost:string; var aErrorMsg:string; var aIsJobDone:Boolean);

    type
     DoJob = class(TThread)
     private
       fHost,fErrorMsg:string;
       fIsJobDone:Boolean;
     protected
       procedure Execute; override;
     public
       property ErrorMsg:string read fErrorMsg;
       property IsJobDone:Boolean read fIsJobDone;

       constructor Create(const aHost:string; var aErrorMsg:string; var aIsJobDone:Boolean);
       destructor Destroy; override;
     end;

    implementation

    procedure  ThreadDoJob(const aHost:string; var aErrorMsg:string; var aIsJobDone:Boolean);
    var
     ThreadJob:DoJob;
    begin
     ThreadJob:=DoJob.Create(aHost,aErrorMsg,aIsJobDone);
     ThreadJob.WaitFor;
     aErrorMsg:=ThreadJob.ErrorMsg;
     aIsJobDone:=ThreadJob.IsJobDone;
     ThreadJob.Destroy;
    end;

    constructor DoJob.Create(const aHost:string; var aErrorMsg:string; var aIsJobDone:Boolean);
    begin
     inherited Create(False);
     FreeOnTerminate := FALSE;
     Self.Priority := tpLower;
     fHost:=aHost;
    end;

    destructor DoJob.Destroy;
    begin
     inherited Destroy;
    end;

    procedure DoJob.Execute;
    var
     flg:Boolean;
    begin
     flg:=false;  (*or FALSE just for fun*)

     if flg then
     begin
       fIsJobDone:=TRUE;
       fErrorMsg:='7777';
     end
     else
     begin
       fIsJobDone:=FALSE;
       fErrorMsg:='6666';
     end;

     ReturnValue:=1;
    end;

    end.



    все работает. данные входят и выходят
  • Leonid Troyanovsky © (05.06.18 09:42) [20]

    > icp ©   (05.06.18 09:32) [18]

    > какой же тут форгет если он паблик проперти придумал.

    Какая разница паблик  не паблик, если все в одном флаконе.

    Я думаю, что у ТС уже есть все необходимое для
    выполнения домашнего задания.

    --
    Regards, LVT.
  • Leonid Troyanovsky © (05.06.18 09:45) [21]

    > Pcrepair ©   (05.06.18 09:39) [19]

    > подкину дровишек. вот так демо работает. несмотря на выше
    > опубликованный базар

    Зря за базаром не следишь, бо фигню написал.
    О чем еще в [1] сказано.

    --
    Regards, LVT.
  • icp © (05.06.18 10:20) [22]
    разница такая.
    если свойство то нужна ссылка на экземпляр.
    посему надо помнить про поток весь его жизненный цикл.
    никакого форгета здесь и близко не будет
  • icp © (05.06.18 10:26) [23]
    вейтфор. как это прелестно....
    впрочем очередной
    стотысячный велосипедист за последние 18 лет
    на дм.

    они словно однояйцевые как под копирку.
    когда в потоеи начинают.
  • icp © (05.06.18 10:39) [24]
    процессор выполнял полезную работу в основном потоке.
    затем ему сказали потратить кучу тактов и переключиться на вторичный и продолжить творить что то полезное. основной при этом тупо стоит и ничего не делает.

    итого.
    сделали ту же работу но за большее время и потратив
    впустую ресурсы на вторичный поток.

    конгратьюлейшен мистер
  • Leonid Troyanovsky © (05.06.18 17:38) [25]

    > icp ©   (05.06.18 10:20) [22]

    > если свойство то нужна ссылка на экземпляр.
    > посему надо помнить про поток весь его жизненный цикл.


    type
     TMyThread = class(TThread)
     public
       prop: Longint;
       procedure Execute; override;
     end;

    procedure TMyThread.Execute;
    begin
     prop := GetTickCount;
     Sleep(3000);
    end;

    procedure Tform1.PostMort;
    begin
     with Sender as TMyThread do
       ShowMessage(IntToStr(prop));
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
     with TMyThread.Create(False) do
       begin
         FreeOnTerminate := True;
         OnTerminate := PostMort;
       end;
     ShowMessage('FAF');
    end;

    --
    Regards, LVT.
  • icp © (05.06.18 17:43) [26]
    и чо?
    до самого терминэйт работаем со ссылкой на поток.
    а типа если она сендером прилетела то как бы никто не заметил.
    это не настоящий выстрелил и забыл.
  • Leonid Troyanovsky © (06.06.18 08:57) [27]

    > icp ©   (05.06.18 17:43) [26]

    > и чо?

    Усложним задачу.

    Закоментируем
    // ShowMessage('FAF');
    и жмем кнопаку 40+ раз

    > до самого терминэйт работаем со ссылкой на поток.

    (следим за руками) ссылки не храним, за потоком не следим

    > а типа если она сендером прилетела то как бы никто не заметил

    дык, она ж сама прилетела, я про нее и забыл.
    Так что, все по взрослому, никакого Жюля.

    --
    Regards, LVT.
  • icp © (06.06.18 09:43) [28]
    все так просто?
    навесили он терминейт.
    оке.
    и теперь мы не просто помним о потоке (а мы помним я гарантирую это)
    так мы еще и взяли на себя обязательство что экземпляр класса с обработчиком будет жить дольше самого потока.

    а так да как бы не помним
  • Leonid Troyanovsky © (06.06.18 10:13) [29]

    > icp ©   (06.06.18 09:43) [28]

    > так мы еще и взяли на себя обязательство что экземпляр класса
    > с обработчиком будет жить дольше самого потока.

    Ой, как страшно жить.

    Выбор объекта необходимого уровня - еще тот бином.
    Не умеешь ставить блок -  ставь бутылку.

    Это даже не молчаливое завершение процесса,
    бо все в первичном потоке.

    --
    Regards, LVT.
  • icp © (06.06.18 11:44) [30]
    нутакчо.
    как бы забываем
    но на самом деле живем и помним.
    и уйти раньше терминэйта нельзя ибо будет взрыв.
    о чем спортм то?
 
Конференция "Начинающим" » потоки(TThread) и свойства(property), не все понятно
Есть новые Нет новых   [118639   +41][b:0][p:0.003]