Мне нужно отправить массив байтов TCP через приложение FMX на устройство. У меня есть этот интерфейс:
type
IPacketSend = interface
procedure SendAsync(const Msg: String; OnSuccess: TSendSuccess; OnError: TSendError);
end;
Я должен использовать многопоточность, чтобы не блокировать пользовательский интерфейс. Этот класс на самом деле отправляет сообщение в очень упрощенной версии:
type
TPacketSenderLAN = class(TInterfacedObject, IPacketSend)
private
FSelf: IPacketSend;
public
procedure SendAsync(const Msg: String; OnSuccess: TSendSuccess; OnError: TSendError);
end;
implementation
{ TPacketSender<T> }
procedure TPacketSenderLAN.SendAsync(const Msg: String; OnSuccess: TSendSuccess;
OnError: TSendError);
begin
TTask.Run(
procedure
var
Client: TIdTCPClient;
Exc: TObject;
begin
Client := TIdTCPClient.Create(nil);
try
try
Client.Host := '192.168.0.213';
Client.Port := 5200;
Client.ConnectTimeout := 3500;
Client.Connect;
Data := TIdBytes(...);
Client.Socket.Write(Data);
TThread.Synchronize(nil,
procedure
begin
OnSuccess;
FSelf := nil;
end
);
except
on E: Exception do
begin
Exc := AcquireExceptionObject;
TThread.Synchronize(nil,
procedure
begin
OnError(Exception(exc).Message);
FSelf := nil;
end
);
end;
end;
finally
Client.Free;
end;
end
);
end;
end.
Переменная FSelf
абсолютно необходима, потому что с FSelf := Self;
в конструкторе я предотвращаю подсчет ссылок до go до 0, когда рабочий поток выполняется. На самом деле я звоню ...
TThread.Synchronize(nil,
procedure
begin
OnSuccess;
FSelf := nil;
end
);
... где FSelf := nil;
находится в конце, так что объект удаляется по окончании работы. Я называю это таким образом из кода:
var
PacketSender: IPacketSend;
begin
PacketSender := TPacketSenderLAN.Create(...);
end;
Учитывая приведенный выше сценарий, мой вопрос:
Безопасно ли я использую TIdTCPClient? Должен ли я отключить его?
Я не знаю, стоит ли мне звонить Client.Disconnect;
внутри блока finally. Я думаю, что это не нужно, потому что Free уничтожит TIdTCPClient
и, таким образом, клиент отключится. Мой код безопасен?