Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-11

sleep function don't passed before executing the next statement

13 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Eric Kom

Good day,

after included the Crt library in my lazarus file, when I called the functions sleep() or delay(), the function do not execute the previous statement, pass and execute the next as below:

StatusBar.SimpleText := 'My name is Tux';
sleep(100);
StatusBar.SimpleText := 'am ready';
Kind Regards Eric Kom System Administrator - Metropolitan College _________________________________________ / You are scrupulously honest, frank, and \ | straightforward. Therefore you have few | \ friends. / ----------------------------------------- \ \ .--. |o_o | |:_/ | // \ \ (| Kom | ) /'\_ _/`\ \___)=(___/ 2 Hennie Van Till, White River, 1240 Tel: 013 750 2255 | Fax: 013 750 0105 | Cell: 078 879 1334 | www.kom.za.net | www.kom.za.org | www.erickom.co.za Key fingerprint: 513E E91A C243 3020 8735 09BB 2DBC 5AD7 A9DA 1EF5

Reply by email

Michael Schnell
to Eric Kom
Eric Kom wrote 9 lines
after included the Crt library in my lazarus file, when I called the functions sleep() or delay(), the function do not execute the previous statement, pass and execute the next as below: StatusBar.SimpleText := 'My name is Tux'; sleep(100); StatusBar.SimpleText := 'am ready';

Using sleep in this way does not make Any GUI action (i.e. displaying changes) is blocked while the main is sleeping.
- the GUI actions are performed by events and can will be performed at "some reasonable point in time" after the action is scheduled by the user program.

The purpose of sleep() is nothing but "allowing for other threads and processes to use the CPU for at least the given milliseconds".

-Michael

Reply by email

Eric Kom
to Michael Schnell
Michael Schnell wrote 18 lines
On 11/19/2012 10:08 AM, Eric Kom wrote: > > after included the Crt library in my lazarus file, when I called the > functions sleep() or delay(), the function do not execute the > previous statement, pass and execute the next as below: > > StatusBar.SimpleText := 'My name is Tux'; > sleep(100); > StatusBar.SimpleText := 'am ready'; > Using sleep in this way does not make sense at all. - Any GUI action (i.e. displaying changes) is blocked while the main is sleeping. - the GUI actions are performed by events and can will be performed at "some reasonable point in time" after the action is scheduled by the user program.

the Connection procedure is declared as a private

procedure Tfrmform1.Connection(Sender: TObject);
begin
     StatusBar.SimpleText := 'My name is Tux';
     sleep(100);
     StatusBar.SimpleText := 'am ready';
end;
Show quoted text 12 lines
The purpose of sleep() is nothing but "allowing for other threads and processes to use the CPU for at least the given milliseconds". -Michael -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Kind Regards Eric Kom System Administrator - Metropolitan College _________________________________________ / You are scrupulously honest, frank, and \ | straightforward. Therefore you have few | \ friends. / ----------------------------------------- \ \ .--. |o_o | |:_/ | // \ \ (| Kom | ) /'\_ _/`\ \___)=(___/ 2 Hennie Van Till, White River, 1240 Tel: 013 750 2255 | Fax: 013 750 0105 | Cell: 078 879 1334 | www.kom.za.net | www.kom.za.org | www.erickom.co.za Key fingerprint: 513E E91A C243 3020 8735 09BB 2DBC 5AD7 A9DA 1EF5

Reply by email

Michael Schnell
to Eric Kom
Eric Kom wrote
the Connection procedure is declared as a private

This makes no difference at all.

("private" is just a visibility attribute and has no influence on the functionality whatsoever. Please read the docs on the Object Pascal language.)

-Michael

Reply by email

Eric Kom
to Michael Schnell
Michael Schnell wrote 8 lines
On 11/19/2012 11:01 AM, Eric Kom wrote: > the Connection procedure is declared as a private > This makes no difference at all. ("private" is just a visibility attribute and has no influence on the functionality whatsoever. Please read the docs on the Object Pascal language.)

Please did know a link that can send me to Object Pascal Language guide?

Show quoted text 9 lines
-Michael -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Kind Regards Eric Kom System Administrator - Metropolitan College _________________________________________ / You are scrupulously honest, frank, and \ | straightforward. Therefore you have few | \ friends. / ----------------------------------------- \ \ .--. |o_o | |:_/ | // \ \ (| Kom | ) /'\_ _/`\ \___)=(___/ 2 Hennie Van Till, White River, 1240 Tel: 013 750 2255 | Fax: 013 750 0105 | Cell: 078 879 1334 | www.kom.za.net | www.kom.za.org | www.erickom.co.za Key fingerprint: 513E E91A C243 3020 8735 09BB 2DBC 5AD7 A9DA 1EF5

Reply by email

Martin
to Eric Kom
Eric Kom wrote 10 lines
On 19/11/2012 13:07, Michael Schnell wrote: > On 11/19/2012 11:01 AM, Eric Kom wrote: >> the Connection procedure is declared as a private >> > This makes no difference at all. > > ("private" is just a visibility attribute and has no influence on the > functionality whatsoever. Please read the docs on the Object Pascal > language.) Please did know a link that can send me to Object Pascal Language guide?

This isn't so much about object programming, but about event driven programming.

Events are processed one by one. Your "Tfrmform1.Connection" is one event. All other events are only processed, when this returns/finishes. (or when you call Application.ProcessMessages)

"StatusBar.SimpleText := 'My name is Tux'; "
Does store the new caption, but not yet paint it. It triggers a paint event, that will be processed later.

During the sleep no events are processed, so nothing is painted to the screen.

You could call Application.ProcessMessages before the sleep. But
*warning*, this can get messy. During a Application.ProcessMessages your
event ("Tfrmform1.Connection") can be triggered and called again, like this:
     StatusBar.SimpleText := 'My name is Tux';
     Application.ProcessMessages;
           StatusBar.SimpleText := 'My name is Tux';
           Application.ProcessMessages
                  // ... and maybe called again ...
           sleep(100);
           StatusBar.SimpleText := 'am ready';
     sleep(100);
     StatusBar.SimpleText := 'am ready';

You can also try

   StatusBar.Update;

This will (or should) do an immediate paint (do NOT call paint directly!)

Also note: during a sleep your app does not react. If a user resizez the window, it will not paint. So if you put is longer sleeps, your app will become none responsive to the user.

Reply by email

Eric Kom
to Martin
Martin wrote 41 lines
On 19/11/2012 12:17, Eric Kom wrote: > On 19/11/2012 13:07, Michael Schnell wrote: >> On 11/19/2012 11:01 AM, Eric Kom wrote: >>> the Connection procedure is declared as a private >>> >> This makes no difference at all. >> >> ("private" is just a visibility attribute and has no influence on >> the functionality whatsoever. Please read the docs on the Object >> Pascal language.) > Please did know a link that can send me to Object Pascal Language guide? This isn't so much about object programming, but about event driven programming. Events are processed one by one. Your "Tfrmform1.Connection" is one event. All other events are only processed, when this returns/finishes. (or when you call Application.ProcessMessages) "StatusBar.SimpleText := 'My name is Tux'; " Does store the new caption, but not yet paint it. It triggers a paint event, that will be processed later. During the sleep no events are processed, so nothing is painted to the screen. You could call Application.ProcessMessages before the sleep. But *warning*, this can get messy. During a Application.ProcessMessages your event ("Tfrmform1.Connection") can be triggered and called again, like this: StatusBar.SimpleText := 'My name is Tux'; Application.ProcessMessages; StatusBar.SimpleText := 'My name is Tux'; Application.ProcessMessages // ... and maybe called again ... sleep(100); StatusBar.SimpleText := 'am ready'; sleep(100); StatusBar.SimpleText := 'am ready';

Thanks for all Martin, it's works

StatusBar.SimpleText := 'My name is Tux';
StatusBar.Update;
sleep(2000);
StatusBar.SimpleText := 'am ready';

I will try the hard code also

Show quoted text 16 lines
You can also try StatusBar.Update; This will (or should) do an immediate paint (do NOT call paint directly!) Also note: during a sleep your app does not react. If a user resizez the window, it will not paint. So if you put is longer sleeps, your app will become none responsive to the user. -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Kind Regards Eric Kom System Administrator - Metropolitan College _________________________________________ / You are scrupulously honest, frank, and \ | straightforward. Therefore you have few | \ friends. / ----------------------------------------- \ \ .--. |o_o | |:_/ | // \ \ (| Kom | ) /'\_ _/`\ \___)=(___/ 2 Hennie Van Till, White River, 1240 Tel: 013 750 2255 | Fax: 013 750 0105 | Cell: 078 879 1334 | www.kom.za.net | www.kom.za.org | www.erickom.co.za Key fingerprint: 513E E91A C243 3020 8735 09BB 2DBC 5AD7 A9DA 1EF5

Reply by email

Bernd
to Eric Kom

2012/11/19 Eric Kom :

Show quoted text 9 lines
Thanks for all Martin, it's works StatusBar.SimpleText := 'My name is Tux'; StatusBar.Update; sleep(2000); StatusBar.SimpleText := 'am ready'; I will try the hard code also

You should generally try your best to avoid using Sleep() in the above way in most cases. If you have a very simple sequence of waiting times (in your example you have only one) you can easily get away with simply placing a TTimer onto your form and using that to generate a *second* event when the 2 seconds have passed. Using your example with the status bar text in the first event you would set the statusbar text to 'My name is Tux', then start the timer and let your method return. In the timer event set the status bar text to 'am ready' and then also immediately return. During the 2 seconds between these two events the GUI will stay fully functional because nothing is blocking the main thread and other events are able to fire as needed.

The more complicated solution would be to start a thread in the first event and let the thread do the sleep (or the long running task) but note that it is absolutely *not* allowed to directly call any LCL methods from within this worker thread (this makes it slightly more complicated) you would need to use Synchronize() or Application.QueueAsyncCall() to notify the main thread.

The general idea is to make sure all your event methods will return as fast as possible because all the GUI is running from within only one thread (the main thread) and this is basically the only thread that should *never* sleep or block or do long computations. As long as one of your event methods is wasting time in Sleep() (or doing other long running things) the entire GUI will be frozen during this time, this will give a very bad user experience, no other events will be able to fire during this time, no resize, no screen update (this is what you observed), not even closing the form will be possible.

There are some concepts you should study, they are not restricted to Lazarus, most GUI frameworks use the event driven concept, so even if you understand how it works (or how you would do it) for example in C++/Qt or Java/Swing or in GTK or in wxWidgets or basically almost any other framework then you can apply the same knowledge to FPC/Lazarus. Only the Methods will have different names but the problems and their solutions are the same. Try to find examples, discussions, etc. about the following topics:

"event driven programming"
"TTimer"
"worker threads"
"TThread" and "TThread.Synchronize"
"TApplication.QueueAsyncCall"

And if you are doing networking (I am inferring this from the name of your method) I strongly recommend using the LNet components, LNet has an extremely neat architecture and a fully asynchronous event driven model (no sleeping, no blocking ever) that fits nicely into the rest of LCL. Unfortunately it is not very extensively documented but on the other hand it is very small (only ~1000 lines without the optional protocol units) and its actually quite easy to use.

Reply by email

Michael Schnell
to Bernd
Bernd wrote
You should generally try your best to avoid using Sleep() in the above way in most cases.

I would go so fat saying that in a GUI project sleep in the main thread is strictly forbidden, as it produces nothing but confusion.

(Same is true for any "busy wait" polling loops in the main thread and "busy wait" polling loops without sleep in worker threads.)

-Michael

Reply by email

Mark Morgan Lloyd
to Michael Schnell
Michael Schnell wrote 8 lines
On 11/21/2012 09:35 AM, Bernd wrote: > You should generally try your best to avoid using Sleep() in the above > way in most cases. I would go so fat saying that in a GUI project sleep in the main thread is strictly forbidden, as it produces nothing but confusion. (Same is true for any "busy wait" polling loops in the main thread and "busy wait" polling loops without sleep in worker threads.)

Also much database stuff in my experience. *Anything* which doesn't return immediately is very bad news from a usability POV.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Hans-Peter Diettrich
to Mark Morgan Lloyd
Show quoted text 7 lines
Michael Schnell wrote: > (Same is true for any "busy wait" polling loops in the main thread and > "busy wait" polling loops without sleep in worker threads.) Also much database stuff in my experience. *Anything* which doesn't return immediately is very bad news from a usability POV.

IMO there is no strict borderline between possibly lengthy operations, from loading an file into memory up to loading a complex database query result. When the user cannot proceed unless the operation has finished, the GUI can wait that time, too.

That's different from true background operations, found in most IDE's. An IDE can load and parse related files in the background, or scan the current file after each keystroke. These tasks certainly must not block any user actions, and consequently should be moved into threads.

DoDi

Reply by email

Mark Morgan Lloyd
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 13 lines
Mark Morgan Lloyd schrieb: > Michael Schnell wrote: >> (Same is true for any "busy wait" polling loops in the main thread >> and "busy wait" polling loops without sleep in worker threads.) > > Also much database stuff in my experience. *Anything* which doesn't > return immediately is very bad news from a usability POV. IMO there is no strict borderline between possibly lengthy operations, from loading an file into memory up to loading a complex database query result. When the user cannot proceed unless the operation has finished, the GUI can wait that time, too.

I agree. But when loading a (local) file a program can estimate how long it's going to take based on its size, while there is no way to estimate how long a query will take to run and transfer a resultset since even a simple count() depends on the number of matching rows rather than anything which can be immediately deduced from the query text.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Mark Morgan Lloyd
to Hans-Peter Diettrich: IMO there is no strict borderline between possibly lengthy operations, from loading an…
Hans-Peter Diettrich wrote 13 lines
Mark Morgan Lloyd schrieb: > Michael Schnell wrote: >> (Same is true for any "busy wait" polling loops in the main thread >> and "busy wait" polling loops without sleep in worker threads.) > > Also much database stuff in my experience. *Anything* which doesn't > return immediately is very bad news from a usability POV. IMO there is no strict borderline between possibly lengthy operations, from loading an file into memory up to loading a complex database query result. When the user cannot proceed unless the operation has finished, the GUI can wait that time, too.

Actually, I think there is a distinction here. A routine loading a file can recognise that it's in the foreground thread and make the occasional Application.ProcessMessages call, but in the general case I don't think there's provision for an OnIdle callback in database drivers. I think that Delphi/BDE had something like that, but it only worked for Oracle ODBC.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email