Лучший способ дождаться двух событий в Delphi

#delphi

#delphi

Вопрос:

У меня есть класс, в котором есть внутренняя очередь и объект подключения к серверу. Когда элемент помещается в очередь, создается соединение, и элемент обрабатывается, соединение уничтожается, а затем цикл ожидает следующего элемента в очереди.

Я хочу, чтобы после создания соединения сохранялось созданное в течение X секунд / минут, в случае нажатия какого-либо нового элемента мне не нужно заново создавать и повторно аутентифицировать соединение. Вот пример:

 program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Classes, System.Generics.Collections, System.Threading;

type
  TConn = class
  public
    procedure Authenticate;
  end;

  TMyClass = class
  private
    FQueue: TThreadedQueue<TProc<TConn>>;
    FTask: ITask;
    procedure Start;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Push(Proc: TProc<TConn>);
  end;

{ TConn }

procedure TConn.Authenticate;
begin

end;

{ TMyClass }

constructor TMyClass.Create;
begin
  FQueue := TThreadedQueue<TProc<TConn>>.Create;
  Start;
end;

destructor TMyClass.Destroy;
begin
  FQueue.DoShutDown;
  FQueue.Free;
  inherited;
end;

procedure TMyClass.Push(Proc: TProc<TConn>);
begin
  FQueue.PushItem(Proc);
end;

procedure TMyClass.Start;
var
  Proc: TProc<TConn>;
  Conn: TConn;
begin
  FTask := TTask.Run(procedure
  begin
    while not FQueue.Shutdown or (FQueue.QueueSize > 0) do
    begin
      //Blocked by internal TMonitor, released when DoShutdown is called or PushItem
      FQueue.PopItem(Proc);

      if FQueue.ShutDown then
        Exit;

      Conn := TConn.Create;
      Conn.Authenticate;
      Proc(Conn);
      Conn.Free;
    end;
  end);
end;

var
  MyClass: TMyClass;
begin
  try
    MyClass := TMyClass.Create;
    MyClass.Push(procedure(AParam: TConn)
    begin
      //use conn
    end);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
 

При вызове Conn.Free я хочу подождать и оставить его созданным на некоторое время. Если истечет время ожидания X секунд / минут, соединение будет уничтожено и воссоздано в следующем элементе.

Является ли таймер лучшим подходом здесь? Я не люблю использовать таймеры, но в данном случае, я думаю, это имеет смысл.

Я мог бы использовать тайм-аут TThreadedQueue, но тайм-аут устанавливается при создании объекта и используется при ожидании PopItem . Я хотел дождаться только создания соединения, если соединения нет, нет смысла использовать этот тайм-аут. Если бы тайм-аут TThreadedQueue был доступен в prop, я мог бы установить его при создании conn, а затем, после уничтожения, вернуться к бесконечности. Но это не так.

Есть предложения?

Комментарии:

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

2. В этом случае соединение осуществляется с сервером приложений. На сервере есть пул подключений к базе данных. Здесь, в клиенте, у меня есть только одно соединение с сервером. Существует соединение по умолчанию (используемое основным потоком), я хочу реализовать это второе фоновое соединение

3. @RodrigoCaetano вы уже знаете концепцию объединения и кэширования, так что же мешает вам сделать то же самое здесь? Просто сделайте объект connection глобальной / переменной-членом, а не локальной переменной, и поставьте рядом с ним таймер. Если объект не создан, создайте его. В противном случае, если таймер еще не истек, повторно используйте объект. В противном случае уничтожьте и воссоздайте объект. Когда процесс будет завершен, сбросьте таймер.

4. соединение @RemyLebeau уже является переменной класса в одноэлементном (в исходном коде). То, что вы описали, — это оригинальная идея использования timer. У меня просто не очень хороший опыт использования таймеров, поэтому я стараюсь его не использовать. Мой вопрос в том, есть ли другой способ, или таймер действительно является лучшим вариантом здесь

5. @RemyLebeau Итак, согласно вашему ответу, таймер действительно является лучшим подходом.