title: Receive partial data with timeout using TIdTcpClient
body: <p>How to receive a 100-byte-string with following conditions using TIdTcpClient ?:</p>
  
  <ul>
  <li>If nothing comes in, the Read call shall be blocking and thread will wait eternally</li>
  <li>If 100 bytes were received the Read call should return the byte string</li>
  <li>If more than 0 bytes, but less than 100 were received, Read call should return after some timeout (say 1 second) in order to return at least something in a reasonable time, without producing timeout exception, because exception handling in Delphi IDE's debug mode hasn't been made convenient.</li>
  </ul>
  
  <p>My not optimal code for now is as follows:</p>
  
  <pre><code>unit Unit2;
  
  interface
  
  uses
    System.Classes, IdTCPClient;
  
  type
    TTcpReceiver = class(TThread)
    private
      _tcpc: TIdTCPClient;
      _onReceive: TGetStrProc;
      _buffer: AnsiString;
      procedure _receiveLoop();
      procedure _postBuffer;
    protected
      procedure Execute(); override;
    public
      constructor Create(); reintroduce;
      destructor Destroy(); override;
      property OnReceive: TGetStrProc read _onReceive write _onReceive;
    end;
  
  implementation
  
  uses
    System.SysUtils, Vcl.Dialogs, IdGlobal, IdExceptionCore;
  
  constructor TTcpReceiver.Create();
  begin
    inherited Create(True);
    _buffer := '';
    _tcpc := TIdTCPClient.Create(nil);
    //_tcpc.Host := '192.168.52.175';
    _tcpc.Host := '127.0.0.1';
    _tcpc.Port := 1;
    _tcpc.ReadTimeout := 1000;
    _tcpc.Connect();
    Suspended := False;
  end;
  
  destructor TTcpReceiver.Destroy();
  begin
    _tcpc.Disconnect();
    FreeAndNil(_tcpc);
    inherited;
  end;
  
  procedure TTcpReceiver.Execute;
  begin
    _receiveLoop();
  end;
  
  procedure TTcpReceiver._postBuffer();
  var buf: string;
  begin
    if _buffer = '' then Exit;
    buf := _buffer;
    _buffer := '';
    if Assigned(_onReceive) then begin
      Synchronize(
        procedure()
        begin
          _onReceive(buf);
        end
      );
    end;
  end;
  
  procedure TTcpReceiver._receiveLoop();
  var
    c: AnsiChar;
  begin
    while not Terminated do begin
      try
        c := AnsiChar(_tcpc.IOHandler.ReadByte());
        _buffer := _buffer + c;
        if Length(_buffer) &gt; 100 then
          _postBuffer();
      except
        //Here I have to ignore EIdReadTimeout in Delphi IDE everywhere, but I want just to ignore them here
        on ex: EIdReadTimeout do _postBuffer();
      end;
    end;
  end;
  
  end.
  </code></pre>