Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

INDY 10 TCP Server - Combine with non thread safe VCL Code

VCL is not thread safe. Therefore I guess it is not a good idea to write information to the gui in the INDY 10 TCP server.execute(...) function .

How to send information from the server execute to the VCL ?

I need to modify a TBitmap inside a tcpserver.execute function. How to make that thread safe ?

like image 420
user1769184 Avatar asked Oct 23 '12 18:10

user1769184


2 Answers

Write stuff to the VCL thread from Indy the same way to write stuff to the VCL thread from anywhere else. Common options include TThread.Synchronize and TThread.Queue.

Modifying a standalone TBitmap should not require synchronization with the main thread. You can modify it from any thread you want, as long as you do it from only one thread at a time. You can use the standard synchronization objects like critical sections and events to make sure only one thread uses it at a time.

like image 127
Rob Kennedy Avatar answered Sep 19 '22 16:09

Rob Kennedy


the best way to synch is by creating and using a TidNotify descendant.

define a tidnotify descendant and vcl proc like this with the appropriate private fields.

TVclProc= procedure(aBMP: TBitmap) of object;

TBmpNotify = class(TIdNotify)
protected
  FBMP: TBitmap;
  FProc: TVclProc;
  procedure DoNotify; override;
public
  constructor Create(aBMP: TBitmap; aProc: TVclProc); reintroduce;
  class procedure NewBMP(aBMP: TBitmap; aProc: TVclProc);
end;

then implement it like this

{ TBmpNotify }

constructor TBmpNotify.Create(aBMP: TBitmap; aProc: TVclProc);
begin
  inherited Create;
  FBMP:= aBMP;
  FProc:= aProc;
end;

procedure TBmpNotify.DoNotify;
begin
  inherited;
  FProc(FBMP);
end;

class procedure TBmpNotify.NewBMP(aBMP: TBitmap; aProc: TVclProc);
begin
  with Create(aBMP, aProc) do
  begin
    Notify;
  end;

end;

then from the

server.execute(...)

call it like this

procedure TTCPServer.DoExecute(aContext: TIdContext);
var
  NewBMP: TBitmap;
begin
  TBmpNotify.NewBMP(NewBMP, FVclBmpProc);  
end;

Where the FVclBmpProcis a private field pointing to a procedure on the form that matches the parameter signature of TVclProc. This field should be set via a property on the server object just after creation and before starting the server.

the method on the form will be free to use the bitmap it receives without fear of thread contention, deadlock and other nasties created by accessing the VCL controls without synchronisation.

like image 24
Mike Taylor Avatar answered Sep 18 '22 16:09

Mike Taylor