Indy синхронизировать ServerTCPExecute

Я использую компонент TIDTCPServer. Как я поняла событие ServerTCPExecute(AContext: TIdContext) не синхронизируется. Каков наилучший способ синхронизации? Мне нужно, чтобы данные отправлялись в основной поток и возвращались к формату ответа.

Я использую Indy 10.5.8.0.

Способ 1

Это что-то вроде этого, я должен иметь дело с критическими секциями для передачи данных из несинхронизированной функции в приложение?

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;

2 ответа

Решение

Правильный способ заключается в использовании Indy's TIdSync вместо доступа к внутренним потокам Indy, например:

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;

Просто будьте осторожны с любой синхронизацией, которую вы делаете, будь то TIdSync или же TThread.Synchronize(), Если основной поток пытается деактивировать сервер во время синхронизации сервера с основным потоком, вы заблокируете как основной поток, так и сервер.

В моем приложении я использую этот код:

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

Обязательно используйте критическую секцию или другой объект синхронизации, если вам нужен доступ к переменным основного потока в ServerTCPExecute

Другие вопросы по тегам