I have now looked over the code and I am not understanding why the OnStatusChange event could not be used to manage the connection...
It seems like it is there just in order to handle these things.
Will this not work:
I changed the thread according to your suggestions, like using Connected as a property and reading all available bytes, but a question here:
I have set a read timeout of 100 ms, which means that the Execute will loop on that time if there are no data, right?
So the thread can be terminated properly within that time.
Is this OK:
If the ReadBytes call would be blocking forever, how can the thread end if it blocks in the execute procedure?
Is it even possible to quit it from the main application?
I believe there must be a timeout here, correct?
Edit:
I am programming this class without being able to test it because the main application it is part of does not build yet and there are tons of Delphi/Windows things that need to be fixed there first...
So the most I can do now with this is to do syntax checks.
It seems like it is there just in order to handle these things.
Will this not work:
Code:
property Connected: boolean read FConnected;
...
procedure TTcpClientComm.Connect(Host: string; Port: word);
begin
FConn.Connect(Host, Port); //Create read thread in OnStatus.hsConnected
end;
procedure TTcpClientComm.Disconnect;
begin
FConn.Disconnect; //Dispose of read thread in OnStatus.hsDisconnected, will also handle client disconnect
end;
procedure TTcpClientComm.OnStatusChange(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string);
{This procedure parses the socket status change messages and manages the read thread}
begin
case AStatus of
hsResolving: ;
hsConnecting: ;
hsConnected:
begin
FReadThread := TReadingThread.Create(Self);
FConnected := true;
end;
hsDisconnecting: FConnected := false;
hsDisconnected:
begin
FConnected := false;
if FReadThread <> NIL then
FReadThread.Terminate;
if FReadThread <> NIL then
begin
FReadThread.WaitFor;
FreeAndNil(FReadThread);
end;
end;
hsStatusText: ;
end;
end;
I changed the thread according to your suggestions, like using Connected as a property and reading all available bytes, but a question here:
I have set a read timeout of 100 ms, which means that the Execute will loop on that time if there are no data, right?
So the thread can be terminated properly within that time.
Is this OK:
Code:
TReadingThread = class(TThread)
protected
FRxData: TIdBytes;
FOwner: TTcpClientComm;
procedure Execute; override;
procedure DoOnRxData;
public
constructor Create(Owner: TTcpClientComm);
end;
implementation
constructor TTcpClientComm.Create;
begin
FConnected := false;
FHost := '';
FPort := 0;
FConn := TIdTCPClient.Create(NIL);
FConn.OnStatus := OnStatusChange;
FConn.ConnectTimeout := 5000; //5 second connect timeout
FConn.ReadTimeout := 100; //Used in the read thread to not block
end;
{ TReadingThread }
procedure TReadingThread.Execute;
begin
while not Terminated do
begin
//Do not use FOwner.FConn.Connected here because that triggers a read operation on the socket...
if FOwner.Connected then //Connected is a property reading the boolean FConnected
begin
FOwner.FConn.IOHandler.ReadBytes(FRxData, -1, False); //Get all available data with timeout
if Assigned(FOwner.FOnRxData) then
Synchronize(DoOnRxData);
end;
end;
end;
procedure TReadingThread.DoOnRxData;
begin
if Assigned(FOwner.FOnRxData) and (Length(FRxData) > 0) then
FOwner.FOnRxData(Self, FRxData);
end;
constructor TReadingThread.Create(Owner: TTcpClientComm);
begin
FOwner := Owner; //Set reference to Owner so we can use the FConn object directly
inherited Create(False);
end;
Is it even possible to quit it from the main application?
I believe there must be a timeout here, correct?
Edit:
I am programming this class without being able to test it because the main application it is part of does not build yet and there are tons of Delphi/Windows things that need to be fixed there first...
So the most I can do now with this is to do syntax checks.