Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.06.2018, 19:37   #1
Pcrepair
Форумчанин
 
Регистрация: 04.01.2011
Сообщений: 260
По умолчанию потоки(TThread) и свойства(property), не все понятно

Добрый день. Есть следующий демокод:

Код:
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; и aIsJobDone:=ThreadJob.IsJobDone; выводят "ничего" в выше стоящий код

Вопрос : как вывести результат работы потока в обработчики но без "Synchronize", трубы и прочего из той же оперы а через "property". если такое для потока вообще возможно. что то читал про OnTerminate но ничего канкретно применительно к "property" не нашлось.
Pcrepair вне форума Ответить с цитированием
Старый 04.06.2018, 20:19   #2
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

К примеру так.
Код:
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:=true;  (*or FALSE just for fun*)

  if flg then
  begin
    fIsJobDone:=TRUE;
    fErrorMsg:='7777';
  end
  else
  begin
    fIsJobDone:=FALSE;
    fErrorMsg:='6666';
  end;
ReturnValue:=1;             {Нужно для WaitFor}
end;
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 04.06.2018, 20:51   #3
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Или мьютекс использовать. Мьютекс не исключает того что нужна архитектура. Так как кривая архитектура приводит к дедлокам и гонкам потокам.

Код:
unit Unit1;

interface
uses
  System.Classes,
  SysUtils,
  StrUtils,
  Windows;

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

type
  DoJob = class(TThread)
  private
    FLock:TRTLCriticalSection; // Нельзя объявлять внутри функции. 
    fHost,fErrorMsg:string;
    fIsJobDone:Boolean;
    procedure Lock;
    procedure UnLock;
    procedure SetErrorMsg(const Value: string);
    procedure SetIsJobDone(const Value: Boolean);
    function GetErrorMsg: string;
    function GetIsJobDone: Boolean;
  protected
    procedure Execute; override;
  public
    property ErrorMsg:string read GetErrorMsg write SetErrorMsg;
    property IsJobDone:Boolean read GetIsJobDone write SetIsJobDone;

    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);
  while not ThreadJob.IsJobDone do ;
  aErrorMsg:=ThreadJob.ErrorMsg;
  ThreadJob.Terminate;
end;

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

destructor DoJob.Destroy;
begin
  DeleteCriticalSection(FLock);
  inherited Destroy;
end;

procedure DoJob.Execute;
var
  flg:Boolean;
begin
  while not Terminated do
    begin
    flg:=Random(100000)=31415;
    if flg or IsJobDone then // После Done  мы не должны изменять своё состояние на False поэтому дописан or IsJobDone
      begin
        ErrorMsg:='7777';  // общий ресурс поэтому без f чтобы безопасно 
        fIsJobDone:=TRUE; // Строка должна быть последней
      end
      else
      begin
        ErrorMsg:='6666';
        IsJobDone:=FALSE;
      end;
    end;
  lock;
end;

function DoJob.GetErrorMsg: string;
begin
  Lock;
  Result:=FErrorMsg;
  UnLock;
end;

function DoJob.GetIsJobDone: Boolean;
begin
  Lock;
  Result:=FIsJobDone;
  UnLock;
end;

procedure DoJob.SetErrorMsg(const Value: string);
begin
  Lock;
  FErrorMsg := Value;
  UnLock;
end;

procedure DoJob.SetIsJobDone(const Value: Boolean);
begin
  Lock;
  FIsJobDone := Value;
  UnLock;
end;

procedure DoJob.Lock;
begin
  EnterCriticalSection(FLock);
end;

procedure DoJob.UnLock;
begin
  LeaveCriticalSection(FLock);
end;

end.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 04.06.2018, 20:56   #4
Pcrepair
Форумчанин
 
Регистрация: 04.01.2011
Сообщений: 260
По умолчанию

большое спасибо, вывод данных есть
и вопрос :
с ThreadJob.WaitFor; ThreadJob.Destroy; и FreeOnTerminate := FALSE; в общем все понятно (перенос запуска остановки потока для передачи параметров пока поток жив)

но что значит ReturnValue:=1; ???

а также WaitFor, если в DoJob.Execute идет процесс асинхронгного обмена данными между клиентом и сервером , будет ли WaitFor правильно работать.

вообще сейчас использую передачу результата в глобПерем(из DoJob.Execute) и таймер на форме для проверки поступления результатов.

будет ли способ передачи-возврата данных через параметры работоспособным в данной ситуации?
Pcrepair вне форума Ответить с цитированием
Старый 04.06.2018, 21:20   #5
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Цитата:
Сообщение от Pcrepair Посмотреть сообщение
но что значит ReturnValue:=1; ???
Для наглядности можно сделать так:
Const ttDone=1;
ReturnValue:=ttDone;
ReturnValue - это просто флаг если число отлично от 0 то WaitFor выходит из цикла.

Цитата:
Сообщение от Pcrepair Посмотреть сообщение
будет ли WaitFor правильно работать.
Это жёсткая блокировка. Если основной поток вам не нужен то всё норм. Если нужен, то надо свой огород городить. Очередь сообщений и прочие вещи. Так что на вашем месте я бы отставил глобальные переменные и таймер. Если не хотите глобальные переменные то каждое поле класса обернуть в мьютекс.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 04.06.2018, 21:21   #6
Pcrepair
Форумчанин
 
Регистрация: 04.01.2011
Сообщений: 260
По умолчанию

еще раз спасибо. буду теперь экспериментировать дальше.
Pcrepair вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

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

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
НЕ все понятно с функцией WMI Pcrepair Общие вопросы Delphi 2 03.03.2016 22:14
Потоки. Закрываются все потоки при ошибке в одном. Son Общие вопросы Delphi 11 01.11.2013 09:32
Можно ли использовать TNotifyEvent через property, в TThread? Человек_Борща Общие вопросы Delphi 4 26.06.2012 19:57
Notice: Trying to get property of non-object. для property of static property Jakethefish PHP 8 16.08.2011 16:09
Потоки(TThread). Возврат значений функции. Delphi_ProGer Общие вопросы Delphi 11 07.08.2011 22:50