5

I'm using TIDTCPServer component. As I understood event ServerTCPExecute(AContext: TIdContext) is not synchronized. What is the best way of synchronising it? I need data to be send to main thread and have them back to format answer.

I'm using Indy 10.5.8.0.

Method 1

Is it something like this I should deal with critical sections to pass data from non synchronized function to application?

var data:string;
.
.
.
procedure MainThreadProcedure;
begin
  ...
end;
.
.
.
procedure IdTCPServerExecute(AContext: TIDContext);
var tmp: string;
begin
.
.
.
EnterCriticalSection(cs);
data:= tmp;
TIdYarnOfThread(AContext.Yarn).Thread.Synchronize(MainThreadProcedure);
LeaveCriticalSection(cs);
end;
vico
  • 17,051
  • 45
  • 159
  • 315

2 Answers2

12

The correct way is to use Indy's TIdSync class instead of accessing Indy's internal threads directly, eg:

uses
  ..., IdSync;

type
  TMySync = class(TIdSync)
  protected
    procedure DoSynchronize; override;
  public
    data: string; 
  end;

procedure TMySync.DoSynchronize;
begin
  // this runs in the main thread
  // use data as needed...
end;

procedure IdTCPServerExecute(AContext: TIDContext); 
var
  tmp: string;
  sync: TMySync; 
begin 
  tmp := ...;
  sync := TMySync.Create;
  try 
    sync.data := tmp; 
    sync.Synchronize;
  finally
    Sync.Free;
  end; 
end;

Just be careful with any synchronizing you do, whether it be TIdSync or TThread.Synchronize(). If the main thread tries to deactivate the server while the server is trying to sync with the main thread, you will deadlock both the main thread and the server.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

In my application, I'm using this code:

procedure MainThreadProcedure;
begin
  ...
end;
.
.
.
procedure IdTCPServerExecute(AContext: TIDContext);
begin
  TIdYarnOfThread(AContext.Yarn).Thread.Synchronize(MainThreadProcedure);
end;

Be sure to use a critical section or other synchronization object if you need to access main thread variables in ServerTCPExecute

iMan Biglari
  • 4,674
  • 1
  • 38
  • 83
  • Thank you for the code. Is it something similar I should deal with critical sections like described in question Method 1? – vico Aug 29 '12 at 14:12
  • Yes. But, **leave the critical section BEFORE Synchronize** or else your main thread will freeze if you plan on entering it in `MainThreadProcedure` – iMan Biglari Aug 29 '12 at 14:21
  • Looks synchronization doesn't works in this case, because if you look to thread debugger you will find that MainThreadProcedure has different thread ID than main application thread. – vico Aug 29 '12 at 15:10
  • I don't know about the thread IDs, but this code works fine in my applications with 500+ TCPClients. Are you getting access violation or memory corruptions? – iMan Biglari Aug 29 '12 at 17:36
  • looks like I found problem. `TIdYarnOfThread(AContext.Yarn).Thread.Synchronize(MainThreadProcedure); ` synchronizes code with main thread, but I need use object that acts in another thread (not main). Have no idea how to do that. – vico Aug 30 '12 at 10:31