Накидал вам пример с использование потокобезопасной очереди.
Логика работы такая - поток получает данные и заталкивает их в очередь, в главной форме, в таймере (можно изменить на OnIdle), проверяем очередь на наличие данных, если данные есть, то обрабатываем их.
Обратите внимание на процедуру создания очереди - FQueue:=TThreadedQueue<TRec_Data>.Create(100, 1000, 10); где первый параметр размер очереди (100), второй таймаут заталкивания данных в очередь (1000мс = 1сек), третьй таймаут вытаскивания из очереди (10 мс - маленький, чтоб таймер у нас не подвисал в ожидании).
Вот код проекта целиком
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
System.Generics.Collections,
IdTCPClient, IdGlobal, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo;
type
TRec_Data = record
Flag: array[0..20] of char;
end;
TMyThread = class(TThread)
private
Progress: string;
Client : TIdTCPClient;
FQueue : TThreadedQueue<TRec_Data>;
protected
procedure Execute; override;
public
constructor Create(const AQueue : TThreadedQueue<TRec_Data>);
destructor Destroy; override;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FQueue : TThreadedQueue<TRec_Data>;
FMyThread : TMyThread;
Timer : TTimer;
procedure OnTimer(Sender: TObject);
public
Memo1: TMemo;
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
FQueue:=TThreadedQueue<TRec_Data>.Create(100, 1000, 10);
Timer:=TTimer.Create(Self);
Timer.Interval:=100;
Timer.OnTimer:=OnTimer;
Timer.Enabled:=True;
FMyThread:=TMyThread.Create(FQueue);
FMyThread.Start;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(FMyThread) then
begin
FMyThread.Terminate;
FMyThread.WaitFor;
FMyThread.Free
end;
if Assigned(Timer) then
Timer.Free;
if Assigned(FQueue) then
FQueue.Free;
end;
procedure TForm1.OnTimer(Sender: TObject);
Var ARec : TRec_Data;
begin
// while FQueue.PopItem(ARec) = TWaitResult.wrSignaled do или
if FQueue.PopItem(ARec) = TWaitResult.wrSignaled then
Form1.Memo1.Lines.Insert(0, ARec.Flag);
end;
constructor TMyThread.Create(const AQueue : TThreadedQueue<TRec_Data>);
var
Rec: TRec_Data;
Buffer: TIdBytes;
begin
inherited Create(true);
FQueue:=AQueue;
Client := TIdTCPClient.Create(nil);
Client.Host := '127.0.0.1';
Client.Port := 6000;
Client.Connect;
// Передаем данные
if Client.Connected = True then
begin
Rec.Flag := 'addUser';
Buffer := RawToBytes(Rec, SizeOf(Rec));
Client.IOHandler.Write(Buffer);
end;
end;
destructor TMyThread.Destroy;
begin
if Assigned(Client) then
Client.Free;
inherited;
end;
procedure TMyThread.Execute;
var
Rec: TRec_Data;
Buffer: TIdBytes;
begin
while Not Terminated do
begin
if Client.Connected then
begin
Client.IOHandler.ReadBytes(Buffer, SizeOf(Rec));
BytesToRaw(Buffer, Rec, SizeOf(Rec));
Progress := Rec.Flag;
// Synchronize(SetProgress);
FQueue.PushItem(Rec);
end
else
Client.Connect;
TThread.Sleep(10);
end;
end;
end.
Так же обратите внимание, я переписал ваш метод Execute на правильный. В вашей реализации, поток завершался при потере соединения.