Recent

Author Topic: Lazarus GUI program, where is the main loop?  (Read 662 times)

BosseB

  • Sr. Member
  • ****
  • Posts: 304
Lazarus GUI program, where is the main loop?
« on: September 28, 2020, 12:24:19 am »
I would like to know where I can place the CheckSynchronize() call in a GUI program such that it is executed regularly a few times per second at least?
In a console program I can put it in a loop at the end of the main program where also the exit conditions are checked and here the messaging from threads work.
But where could I place it in a GUI program?
I have problems receiving data from a TCPIP client I created using Indy10.
The data are retrieved from the wire in a thread and it is supposed to fire off an event when the data arrive. But it seems like CheckSynchronize needs to be executed regularly in the main thread in order for the event to be recognized...
Only I cannot find the main thread loop in a GUI program...
--
Bo Berglund
Sweden

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6716
  • Debugger - SynEdit - and more
    • wiki
Re: Lazarus GUI program, where is the main loop?
« Reply #1 on: September 28, 2020, 12:47:46 am »
TApplication.Run;
Then WidgetSet dependent, then TApplication.RunLoop then .....

But: If your main thread is Idle, it should run CheckSyncronize.

Of course by default an Idle main thread will sleep.
But TApplication.QueueAsync or TThread.Syncronize or TTHread.Queue, they all call WakeMainThread, and then it will do CheckSyncronize.


Of course if your main thread is not idle.... But then its in your code...

jamie

  • Hero Member
  • *****
  • Posts: 3797
Re: Lazarus GUI program, where is the main loop?
« Reply #2 on: September 28, 2020, 03:26:23 am »
I would like to know where I can place the CheckSynchronize() call in a GUI program such that it is executed regularly a few times per second at least?
In a console program I can put it in a loop at the end of the main program where also the exit conditions are checked and here the messaging from threads work.
But where could I place it in a GUI program?
I have problems receiving data from a TCPIP client I created using Indy10.
The data are retrieved from the wire in a thread and it is supposed to fire off an event when the data arrive. But it seems like CheckSynchronize needs to be executed regularly in the main thread in order for the event to be recognized...
Only I cannot find the main thread loop in a GUI program...

Sounds like Linux to me ?

Any ways in Windows the simplest thing to do is just post a message to the main thread and have it handled in some GUI object.

Windows GUI sits in a loop using "GetMessage" so if you post a LM_USER+???? message to a Form for example, it will get processed..
when the message arrives to the form you implement a message handler for which it just goes out and reads the data buffers of the thread of what ever it needs to do..
 
 you don't want the main thread sitting there in a loop reading some change variable in a thread, it has to be allowed to cycle through the normal process of message handling, otherwise windows places a stop to the app as no-response..
The only true wisdom is knowing you know nothing

PascalDragon

  • Hero Member
  • *****
  • Posts: 2429
  • Compiler Developer
Re: Lazarus GUI program, where is the main loop?
« Reply #3 on: September 28, 2020, 09:24:49 am »
I would like to know where I can place the CheckSynchronize() call in a GUI program such that it is executed regularly a few times per second at least?

You don't need to do that, because the LCL already takes care of that.

BosseB

  • Sr. Member
  • ****
  • Posts: 304
Re: Lazarus GUI program, where is the main loop?
« Reply #4 on: September 28, 2020, 09:28:57 am »
OK, here is the situation:
I have a very old set of programs designed about 2003-2004 with Delphi7, later moved to Delphi2007, and running on WindowsXP.

One is a Windows service and the other is a regular GUI program for connecting to the service to do configuration and maintenance and retrieve measurement results. The service schedules regular measurement runs using a hardware data collection system controlled via RS232.

Recently it has become increasingly difficult to get the system reliably running on Windows, it was possible up until Win 7, but now that is no longer possible and Win10 is a PITA due amongst other things to the fact that it insists on rebooting without warning at any time it sees fit.

So I am working on porting the system to Linux instead, specifically to Raspberry Pi, so I will get a stable platform.
But when doing so I have had to invent new components for the TCP/IP and RS232 handling as well as for digital I/O, which was originally using the ISA bus printer port.

So I have created a derivative of the Indy10 IdTcpClient, which has a read thread built in such that I can have the incoming data supplied via an event (Indy itself is blocking and thus much more difficult to use when porting the applications which are built around the event model).
The server runs as a regular non-GUI program and I had to add CheckSynchronize to the main program loop to get the TCP/IP receive event working properly.

I am using the same custom TCP/IP object in the client application and here I am looking for the location to put the CheckSynchronize call since there is no user visible main program loop AFAICT.

Yesterday I finally got both ported programs to build on both Linux and Windows so I could test them and the results indicate that my Lazarus client on Windows does not see the incoming data from the server, whereas the old Windows Delphi client does if I use that to talk to the Linux server.

I have yet to start debugging from within Lazarus, but my suspicion is that the missing part is the absence of the CheckSynchronize call. I might be wrong though and the problem is elsewhere...

OOPS,
while typing this @PascalDragon states that LCL does this in a GUI program. If so the problem is something else...
--
Bo Berglund
Sweden

MarkMLl

  • Hero Member
  • *****
  • Posts: 1458
Re: Lazarus GUI program, where is the main loop?
« Reply #5 on: September 28, 2020, 10:30:20 am »
So I have created a derivative of the Indy10 IdTcpClient, which has a read thread built in such that I can have the incoming data supplied via an event (Indy itself is blocking and thus much more difficult to use when porting the applications which are built around the event model).
The server runs as a regular non-GUI program and I had to add CheckSynchronize to the main program loop to get the TCP/IP receive event working properly.

...

OOPS,
while typing this @PascalDragon states that LCL does this in a GUI program. If so the problem is something else...

You're living dangerously. Back off, and sort it out properly with threads.

I've got a program which is somewhat older than yours where I tried to be clever with an interactive text session embedded in a GUI program... the important bits were largely unchanged from their Turbo Pascal and Win-16 roots. When I started porting it to Lazarus on Linux I had nothing but problems: bad assumptions in my input handling which meant that e.g. dialogue boxes didn't get any CPU time.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

Thaddy

  • Hero Member
  • *****
  • Posts: 10590
Re: Lazarus GUI program, where is the main loop?
« Reply #6 on: September 28, 2020, 11:15:02 am »
Quote
hardware data collection system controlled via RS232
Synaser works on a Raspberry Pi. For the Daemon, have a look at the example. The GUI should not produce many issues when ported to Lazarus.
Should also work on the Raspberry Pi.

BosseB

  • Sr. Member
  • ****
  • Posts: 304
Re: SOLVED Lazarus GUI program, where is the main loop?
« Reply #7 on: September 28, 2020, 02:02:09 pm »
PROBLEM SOLVED
I have now been able to start up both applications and check communications. The server, which ran fine on my development RPi4 yesterday, started from a terminal in the GUI, did not start today when I tried from a PuTTY terminal on Windows. Message:
Code: Text  [Select][+][-]
  1.  $ ./SSRemoteServerLx
  2.  
  3. (SSRemoteServerLx:3212): Gtk-WARNING **: 11:46:18.606: cannot open display:
So I went back and re-enabled the nogui setting ín Project Options/Compiler Options/Additions and Overrides
Then after a new build I could start the server from the PuTTY terminal and it worked OK.

Then I tried the client on Windows and it did work after I had fixed an annoying problem with the ported version:
There is a login form shown modal where after a successful socket connection the user must enter username and password and then click OK. The problem is that this modal form did not close so the whole application hung...
When I stepped through the code I could see that the form OK button actually did not close the form with the mrOk result. So the application was stuck there.

After I fixed this it worked as it should and I could communicate with the server as expected. So Lazarus did not pick up the OK button action properly from the Delphi code...

So two edits fixed it:
- Enable the nogui widgetset in the server
- Change the button results of OK and Cancel on the client login form to mrOk and mrCancel. This should have been there from Delphi...
--
Bo Berglund
Sweden

MarkMLl

  • Hero Member
  • *****
  • Posts: 1458
Re: SOLVED Lazarus GUI program, where is the main loop?
« Reply #8 on: September 28, 2020, 02:26:32 pm »
- Enable the nogui widgetset in the server
- Change the button results of OK and Cancel on the client login form to mrOk and mrCancel. This should have been there from Delphi...

Thanks for the nogui reminder. I wonder whether the other was related to the form's default button in some way?

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

 

TinyPortal © 2005-2018