Search code examples
delphiindy

IdThreadComponent (Indy 9) in Delphi 2007 Error


I'm using IdTCPClient and IdThreadComponent to get some information for a barcode reader. This code, with some changes is working in Delphi 11 and Indy 10 but not in Delphi 2007 and Indy 9:

procedure TPkgSendF1.IdThreadComponent1Run(Sender: TIdCustomThreadComponent);
var
  s: String;
begin
  s := IdTCPClient1.ReadLn('&', 20000, 1500);
  TThread.Queue(nil, procedure  // <== Expected @ but received PROCEDURE
                begin
                  ProcessRead(s);
                end);
end;

// [DCC Error] PkgSendF1.pas(239): E2029 Expression expected but 'PROCEDURE' found

procedure TPkgSendF1.ProcessRead(AValue: string);
begin
  Memo1.Text := AValue;
end;

If I don't use the TThread.Queue I miss some readings. I'll appreciate any help. Francisco Alvarado


Solution

  • Anonymous methods did not exist yet in Delphi 2007, they were introduced in Delphi 2010. As such, TThread.Queue() in D2007 only had 1 version that accepted a TThreadMethod:

    type
      TThreadMethod = procedure of object;
    

    Which means you need to wrap the call to ProcessRead() inside a helper object that has a procedure with no parameters, eg:

    type
      TQueueHelper = class
      public
        Caller: TPkgSendF1;
        Value: String;
        procedure DoProcessing;
      end;
    
    procedure TQueueHelper.DoProcessing;
    begin
      try
        Caller.ProcessRead(Value);
      finally
        Free;
      end;
    end;
    
    procedure TPkgSendF1.IdThreadComponent1Run(Sender: TIdCustomThreadComponent);
    var
      s: string;
    begin
      s := IdTCPClient1.ReadLn('&', 20000, 1500);
      with TQueueHelper.Create do
      begin
        Caller := Self;
        Value := s;
        TThread.Queue(nil, DoProcessing);
      end;
    end;
    

    FYI, Indy (both 9 and 10) has an asynchronous TIdNotify class in the IdSync unit, which you can use instead of using TThread.Queue() directly, eg:

    uses
      IdSync;
    
    type
      TMyNotify = class(TIdNotify)
      public
        Caller: TPkgSendF1;
        Value: String;
        procedure DoNotify; override;
      end;
    
    procedure TMyNotify.DoNotify;
    begin
      Caller.ProcessRead(Value);
    end;
    
    procedure TPkgSendF1.IdThreadComponent1Run(Sender: TIdCustomThreadComponent);
    var
      s: string;
    begin
      s := IdTCPClient1.ReadLn('&', 20000, 1500);
      with TMyNotify.Create do
      begin
        Caller := Self;
        Value := s;
        Notify;
      end;
    end;