Page 1 of 1

Using TPgConnection and TPgAlerter in thread

Posted: Fri 09 Sep 2011 16:21
by chapa
Hello,

Using PgDAC 3.0 beta trial and 9.0.4 server on localhost. Delphi XE2.
Windows 7 x64

I have following case:

In thread I create one TPgConnection object and one TPgAlerter. Attaching OnEvent handler.
OnEvent is never called. Instead I get TPgSQLNotification leak for every notify message I sent from database side.

Then I add TDataModule. Pick TPgConnection and TPgAlerter VCL components. Configure them.
In this case OnEvent is fired for both OnEvent Alerter handlers (thread created and vcl).

How can I work out this behavior? I would like to use Connection and Alerter in thread.

Thanks.

Posted: Mon 12 Sep 2011 13:03
by AlexP
Hello,

I cannot reproduce the problem.
The following code works correctly (the event works) in RAD Studio XE2 and in x32 applications as well as in the x64 ones. Please try to execute this code, and, if it is executed successfully, modify it so that the problem can be reproduced and send it to alexp*devart*com.

Code: Select all

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, DAAlerter, PgAlerter, Data.DB, DBAccess,
  PgAccess, Vcl.StdCtrls;

type
  TAlerterThread = class(TThread)
  private
    FPgConnection: TPgConnection;
    FPgAlerter: TPgAlerter;
  public
    procedure execute; override;
    procedure FPgAlerterEvent(Sender: TObject; const EventName: string;
      PID: Integer; const EventMessage: string);
  end;

  TForm2 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    FAlerterThread: TAlerterThread;
    FPgConnection: TPgConnection;
    FPgAlerter: TPgAlerter;

  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TAlerterThread }

procedure TAlerterThread.execute;
begin
  FPgConnection := TPgConnection.Create(nil);
  FPgConnection.Server := 'db';
  FPgConnection.Port := 5438;
  FPgConnection.Database := 'alexp';
  FPgConnection.Username := 'postgres';
  FPgConnection.Password := 'postgres';
  FPgConnection.LoginPrompt := false;
  FPgConnection.Connect;
  FPgAlerter := TPgAlerter.Create(nil);
  FPgAlerter.Connection := FPgConnection;
  FPgAlerter.Events := 'TestThread';
  FPgAlerter.OnEvent := FPgAlerterEvent;
  FPgConnection.Connect;
  FPgAlerter.Start;
  If not FPgAlerter.Active then
    ShowMessage('error');
end;

procedure TAlerterThread.FPgAlerterEvent(Sender: TObject;
  const EventName: string; PID: Integer; const EventMessage: string);
begin
  ShowMessage(EventName + '; PID: ' + IntToStr(PID));
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
    FPgAlerter.SendEvent('TestThread');
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  FPgConnection := TPgConnection.Create(nil);
  FPgConnection.Server := 'db';
  FPgConnection.Port := 5438;
  FPgConnection.Database := 'alexp';
  FPgConnection.Username := 'postgres';
  FPgConnection.Password := 'postgres';
  FPgConnection.LoginPrompt := false;
  FPgConnection.Connect;
  FPgAlerter := TPgAlerter.Create(nil);
  FPgAlerter.Connection := FPgConnection;
  FPgAlerter.Events := 'TestThread';
  FPgConnection.Connect;
  FPgAlerter.Start;

  FAlerterThread:= TAlerterThread.Create(true);
  FAlerterThread.resume;
end;

end.

Posted: Mon 12 Sep 2011 13:22
by chapa
Hi AlexP,

The catch is as I said, you MUST have no visual components connected.

Try to trigger the event (SendEvent) from thread's PgAlerter with removed (or not connected) visual components.
Run two instances of the application.
No one will fire.

If you connect the visuals, thread event will fire.

Thanks.

Posted: Wed 14 Sep 2011 10:43
by AlexP
Hello,

Thank you for the information.
We've reproduced the problem with TPgAlerter in threads when visual components are not used.
We will notify you as soon as we have any results.