Recent

Author Topic: How to use function LCLIntf.AddEventHandler?  (Read 773 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 742
How to use function LCLIntf.AddEventHandler?
« on: June 20, 2022, 11:21:54 am »
In my GUI-program I want to use function LCLIntf.AddEventHandler to handle some communication with other clients via internet.

Function AddEventHandler is declared as:
Code: Pascal  [Select][+][-]
  1. function AddEventHandler(AHandle: THandle; AFlags: dword; AEventHandler: TWaitHandleEvent;
  2.                          AData: PtrInt): PEventHandler;
My question is about the 1st parameter 'AHandle': what must I use here on Windows and on Linux?

Linux:
The documentation (which is hard stuff for me) https://wiki.freepascal.org/Main_Loop_Hooks says in chapter "Pipes and Process Termination" (which my be wrong for function AddEventHandler):
Quote
For gtk/unix, use the PID to watch as AHandle.
But when I use the PID from function system.GetProcessID as parameter 'AHandle' then I get always a Message in the Console:
Code: Text  [Select][+][-]
  1. (unit1:4198): GLib-WARNING **: 10:25:46.429: ../../../../glib/giounix.c:410Error while getting flags for FD: Ungültiger Dateideskriptor (9)
The line number 4198 is wrong, so it does not help. The 2 German words mean "Invalid filedescriptor".

If I use instead a small number like 0..9 as parameter 'AHandle' then I do NOT get this Message. But with a high random number like 12345 I get this Message too. So I think the PID is here wrong.

Windows:
When I use the PID as parameter 'AHandle' then I get always endless Messages in the Console:
Code: Text  [Select][+][-]
  1. [TWin32WidgetSet.AppProcessMessages] MsgWaitForMultipleObjects returned: 6
  2. [TWin32WidgetSet.AppProcessMessages] MsgWaitForMultipleObjects returned: 6
  3. [TWin32WidgetSet.AppProcessMessages] MsgWaitForMultipleObjects returned: 6
  4. ...
If I use instead a small number like 3 or 7..9 as parameter 'AHandle' then it works, but I don't think this is reliable.

What I want:
I want a hook in the Main Loop, so that my procedure is called frequently, e.g. 10-20 times a second to handle some communication with other clients via internet.

I'm using Lazarus 2.0.10. Thanks in advance.

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: How to use function LCLIntf.AddEventHandler?
« Reply #1 on: June 20, 2022, 05:51:43 pm »
My question is about the 1st parameter 'AHandle': what must I use here on Windows and on Linux?
In Windows, this is a kernel object descriptor (handle), not an ID.
Example:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, StdCtrls, InterfaceBase;
  9.  
  10. type
  11.   TForm1 = class(TForm)
  12.     Memo1: TMemo;
  13.     procedure FormCreate(Sender: TObject);
  14.     procedure FormDestroy(Sender: TObject);
  15.   private
  16.     FTimer: THandle;
  17.     FHandler: PEventHandler;
  18.     procedure EventFire(AData: PtrInt; AFlags: LongWord);
  19.   public
  20.  
  21.   end;
  22.  
  23. var
  24.   Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. {$R *.lfm}
  29.  
  30. uses Windows, LCLIntf;
  31.  
  32. procedure TForm1.EventFire(AData: PtrInt; AFlags: LongWord);
  33. begin
  34.   Memo1.Append(TimeToStr(Time));
  35. end;
  36.  
  37. procedure TForm1.FormCreate(Sender: TObject);
  38. const
  39.   CPeriod = 5 * MSecsPerSec;
  40. var
  41.   DueTime: Int64 = 0; // First call immediately now
  42. begin
  43.   FTimer := CreateWaitableTimer(nil, False, '');
  44.   if not SetWaitableTimer(FTimer, DueTime, CPeriod, nil, nil, False) then
  45.     RaiseLastOSError;
  46.   FHandler := AddEventHandler(FTimer, 0, @EventFire, 0);
  47. end;
  48.  
  49. procedure TForm1.FormDestroy(Sender: TObject);
  50. begin
  51.   CancelWaitableTimer(FTimer);
  52.   RemoveEventHandler(FHandler);
  53.   CloseHandle(FTimer);
  54. end;
  55.  
  56. end.

Hartmut

  • Hero Member
  • *****
  • Posts: 742
Re: How to use function LCLIntf.AddEventHandler?
« Reply #2 on: June 20, 2022, 07:20:33 pm »
Thank you very much ASerge for your reply and your demo. I got it to work and assume that I understand how it works.
Now I have 2 questions left:
 - What can I do on Linux?
 - If I create this special timer on Windows, why don't I use a normal 'TTimer'? Please what are the benefits of your solution over a TTimer-solution, which would work on Linux too?

Thanks for any help.

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: How to use function LCLIntf.AddEventHandler?
« Reply #3 on: June 21, 2022, 05:23:48 pm »
- If I create this special timer on Windows, why don't I use a normal 'TTimer'? Please what are the benefits of your solution over a TTimer-solution, which would work on Linux too?
This is just a demonstration. WaitableTimer is more accurate, but for GUI applications a regular TTimer is usually enough. Especially in such an example, when the kernel object is waited in the same queue as the windows event (WM_TIMER).
AddEventHandler is most often used to wait for the end of pipeline channels, completion of file operations, waiting for directory change events, network sockets, etc.

Hartmut

  • Hero Member
  • *****
  • Posts: 742
Re: How to use function LCLIntf.AddEventHandler?
« Reply #4 on: June 21, 2022, 07:19:06 pm »
Thanks a lot ASerge for that explanations. Now I understand more about the purpose of function AddEventHandler. I had thought, this would be the easiest solution but possibly I was wrong, because I have no handle already.
If there comes no easy suggestion for Linux, I will use a 'TTimer' instead.

 

TinyPortal © 2005-2018