Douglas Ruiz
Douglas Ruiz

Reputation: 93

IdTcpClient Only Receive one time Windows Service

I don't know why but my windows service application only receive the information from my TcpServer one time (At Windows Service Startup), thread still running but always stuck at Service1.Cliente.IOHandler.ReadBytes(FData, szProtocol, False);

Tested on a normal windows application and works fine, but when move to windows service only receive one time and stop. PS: The thread still running.

    constructor TReadingThread.Create(AClient: TIdTCPClient);
begin
  inherited Create(True);
  FClient := AClient;
end;

procedure TReadingThread.Execute;
begin
  FreeOnTerminate := False;

  while not Terminated do
  begin
    if Service1.Cliente.Connected then
    begin
      if not Service1.Cliente.IOHandler.InputBufferIsEmpty then
      begin
        Service1.Cliente.IOHandler.ReadBytes(FData, szProtocol, False);
        if (FData <> nil) and Assigned(FOnData) then Synchronize(DataReceived);
        CriaLog('Received something');
      end;
    end;

    Sleep(1);
  end;
end;

procedure TReadingThread.DataReceived;
begin
  if Assigned(FOnData) then FOnData(FData);
end;

The same code at normal application works fine, but when the application it's a windows service this problem happen.

Answer for Remy, Here is how szProtocol are defined and what more that use:

type
  TCommand = (
    cmdConnect,
    cmdDisconnect,
    cmdLibera);

type
  TClient = record
    HWID    : String[40];
    Msg     : String[200];
 end;

const
  szClient = SizeOf(TClient);

type
  TProtocol = record
    Command: TCommand;
    Sender: TClient;
    DataSize: Integer;
end;

const
  szProtocol = SizeOf(TProtocol);

My TThread Structure who i use to receive informations was defined as:

type
  TDataEvent = procedure(const LBuffer: TIdBytes) of object;

  TReadingThread = class(TThread)
  private
    FClient : TIdTCPClient;
    FData   : TIdBytes;
    FOnData : TDataEvent;
    procedure DataReceived;
  protected
    procedure Execute; override;
  public
    constructor Create(AClient: TIdTCPClient); reintroduce;
    property OnData: TDataEvent read FOnData write FOnData;
  end;

This procedure is who show me what are received from server and i do some actions.

procedure TService1.DataReceived(const LBuffer: TIdBytes);
type
  PTBytes   = ^TBytes;
  PTIdBytes = ^TIdBytes;
var
  LDataSize   : Integer;
  LProtocol   : TProtocol;
begin
  LProtocol := BytesToProtocol(PTBytes(@LBuffer)^);

  case LProtocol.Command of
    cmdLibera:
    begin
    // action
    end;
  end;
end;

and the others functions from TTHread structure:

constructor TReadingThread.Create(AClient: TIdTCPClient);
begin
  inherited Create(True);
  FClient := AClient;
end;

procedure TReadingThread.DataReceived;
begin
  if Assigned(FOnData) then FOnData(FData);
end;

I know the code works because as i said i use it on a normal application (who isn't a service) and all works perfectly, but at service it don't work.

Upvotes: 1

Views: 122

Answers (1)

Douglas Ruiz
Douglas Ruiz

Reputation: 93

The answer is, just add a "packed" and solved the problem, Thanks Remy.

Upvotes: 1

Related Questions