Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Porting old Delphi2007 application using TServerSocket....
#19
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:

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;
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.
Reply


Messages In This Thread
RE: Porting old Delphi2007 application using TServerSocket.... - by BosseB - 09-19-2020, 07:49 AM

Forum Jump:


Users browsing this thread: 3 Guest(s)