Sign in Join

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

Mailing lists / lazarus / 2010-05

LCL messaging system SendMessage and Multi-Threads

15 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

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

Andrew Brunner

Hi there,

I'm having a problem with a thread I have that is using SendMessage to post to a window handle (Ubuntu x64 10.04). The message comes in just fine. The problem is that I want to change the visibility of a component on a form and the program is closing out on ComponentName.Visible:=True; Is there a work around to the messaging system to make them execute under the Application thread? I've seen this under windows. Windows typically handle changing visibilitiy of components unless done in Application Thread.

I'm using today's SVN of Lazarus and FPC. Any ideas on how to adjust visibility w/o the process terminating unexpectedly?

Thanks.

Reply by email

dmitry boyarintsev
to Andrew Brunner
Andrew Brunner wrote 6 lines
I'm having a problem with a thread I have that is using SendMessage to post to a window handle (Ubuntu x64 10.04). ?The message comes in just fine. ?The problem is that I want to change the visibility of a component on a form and the program is closing out on ComponentName.Visible:=True; ?Is there a work around to the messaging system to make them execute under the Application thread?

There's no equivalent for Window's SendMessage() in other systems. But you can replace it with PostMessage + TEvent.WaitFor, something like:

TWorkThread
  procedure  Execute;
public
  WaitEvent : TEvent;
end;
procedure TWorkThread.Execute
begin
  WaitEvent.Reset;
  PostMessage(MainThread, WM_USER, Data, WaitEvent);
  WaitEvent.Wait(INFINITE);
end;
procedure TMainThread.WndProc(var msg, Data, WaitEvent: TEvent);
begin
  case msg of
    WM_USER: begin
       ProcessData;
       WaitEvent.SetEvent;
    end;
end;

However, there's a problem. If the main thread processing loop is finished before processing all Sent messages from another thread, the waiting messages will hang. On windows, they just stop waiting for the sent message.

But according to your task you need to use Synchronize method. (see FPC docs for the methods description)

thanks,
dmitry

Reply by email

Michael Schnell
to Andrew Brunner: I'm having a problem with a thread I have that is using SendMessage to post to a window…

On 05/07/2010 05:49 AM, Andrew Brunner wrote:

in Linux, SendMessage seems to be implemented in a way that is not very compatible to what SendMessage does in Windows. (No wonder: SendMessage is a quite "interesting" Windows API function, that provides lots of side-effects: sometimes it blocks until the tasks is done. sometimes it interprets the parameters given and even transfers memory chunks from one applications to another.)

OTOH, PostMessage is defined to be non-blocking and works just within a single (multi-threaded) application. This seems to be provided by the LCLs "GTK2 Widget Type" in a very Windows compatible way. So you can use this to notify the main thread from a worker thread.

In the main Form you define an appropriate class procedure by "procedure() .... message" and same will be called in the main thread if in some thread you do a postmessage() with the main form's handle and the appropriate message number. Here you can do things like "visible := true".

-Michael

Reply by email

Andrew Brunner
to dmitry boyarintsev: On Fri, May 7, 2010 at 7:49 AM, Andrew Brunner There's no equivalent for Window's…
dmitry boyarintsev wrote
But according to your task you need to use Synchronize method. (see FPC docs for the methods description)

Thanks for the thoughts Dmitry,

Ok. I'm familiar with Synchronize methods but wasn't sure if they were actually executed via the Main Thread and could truly solve the GUI concerns (especially on Linux but even on OSX and Windows).

I guess I'll give it a try and start from there. At one time I think I recall having tried it but had noticed the same effect. But that was a long time ago. Perhaps the semantics have changed since then.

Thanks again!

Reply by email

Michael Schnell
to Andrew Brunner
Andrew Brunner wrote
Ok. I'm familiar with Synchronize methods but wasn't sure if they were actually executed via the Main Thread and could truly solve the GUI concerns (especially on Linux but even on OSX and Windows).

That is what Synchronize has been invented for: Execute some of the thread code in the main thread.

When calling Synchronize the thread stop at this point. the synchronized method is scheduled to be executed in the main thread. When (after a possibly very long time) the main thread is ready to execute that method, it does so and after that wakes up the thread.

Advantage: you don't need to bother about protecting resources used both by the main worker thread and the thread.

Disadvantage: the worker thread might stop for a very long time.

To prevent the thread from stopping, PostMessage() can be used and the "synchronized" Method now is defined by procedure ... message in of some Form.

Disadvantage: you need to take care of protecting commonly used resources.

-Michael

Reply by email

Andrew Brunner
to Michael Schnell
That is what Synchronize has been invented for: Execute some of the thread code in the main thread.

I had given up on that and went with a SendMessage System under windows. I rarely use it for GUI work but recently the OnSelectItem of the ListView in Ubuntu
is posting up to 3 OnSelectItem events every time I select an item. So my timer system is ideal for refreshing the TTL on the item before it executes the procedure.

Show quoted text 6 lines
When calling Synchronize the thread stop at this point. the synchronized method is scheduled to be executed in the main thread. When (after a possibly very long time) the main thread is ready to execute that method, it does so and after that wakes up the thread. Disadvantage: the worker thread might stop for a very long time.

Yes. I realize that. But it is a necessity for doing GUI work since Gnome or GTK2
won't accept visibility changes from outside threads...

Show quoted text 5 lines
To prevent the thread from stopping, PostMessage() can be used and the "synchronized" Method now is defined by procedure ... message in of some Form. Disadvantage: you need to take care of protecting commonly used resources.

SendMessage did not work. Visibility as not able to be changed. Only synchronize worked.

Thanks for your insight - solved the issue in like the first 10 minutes ;-)

Consequently I really am disappointed at the process GDM @ least for Ubuntu x64. The GDM
keeps crashing on mult-thread debugging and you can't do squat with GUI components from
threads.

Reply by email

Michael Schnell
to Andrew Brunner
Andrew Brunner wrote
But it is a necessity for doing GUI work since Gnome or GTK2 won't accept visibility changes from outside threads...

AFAIK as well with Delphi as with all LCL GUI Widgetr types accessing the GUI from a worker thread is forbidden. But of course you don't need to use "synchronize" to have the main thread change the visibility. you can use any means available to notify the main thread from the worker thread. E.g a global variable the main thread thread watches or using PostMessage().

SendMessage did not work. Visibility as not able to be changed. Only synchronize worked.

As already said, in Linux SendMessage (other that PostMessage) is not implemented (or possible to be implemented) in a way that adheres to the Windows API description. So I would not use it at all, as it's not documented in any way.

Thanks for your insight - solved the issue in like the first 10 minutes ;-)

Great !

-Michael

Reply by email

Michael Schnell
to Zaher Dirkey

On 05/07/2010 05:12 PM, Zaher Dirkey wrote:IMHO, PostMessage is decently implemented in the LCL, works fine and the documentation from the Windows API description applies, So I do use it. For SendMessage the documentation from the Windows API description does not apply and as there is no documentation generated by the LCL providers, IMHO you can't use it with non-Windows Lazarus projects.

-Michael

Reply by email

Zaher Dirkey
to Michael Schnell

In fact i want to understand your discusses here, for example Delphi use PostMessage to send message to Form to close instead to close it by free it as an object, e.g.
In click Button in the Form1 we call Close, but if Close just destroy the form it will destroy the button (and all components) then the code inside Click will use destroyed objects.

I use PostMessage to resolve similar problem for popup controls because the message received after the code in the event OnClick run, i feel in wrong way or am i in wrong discusses.

Thanks

Zaher Dirkey -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20100507/dec86823/attachment.html>

Reply by email

Michael Schnell
to Zaher Dirkey

When I said that the Windows documentation of PostMessage can be used, I did not think of the description of the messages to be sent by PostMessage. Same might be Windows-specific and in the LCL not ported (or portable) to Linux Widget Types like GTK. Here I suppose a documentation is lacking and thus only "user message" can be used, that you receive in your own Pascal code (e.g. by procedure ... message).

-Michael

Reply by email

Zaher Dirkey
to Michael Schnell
Michael Schnell wrote 5 lines
When I said that the Windows documentation of PostMessage can be used, I did not think of the description of the messages to be sent by PostMessage. Same might be Windows-specific and in the LCL not ported (or portable) to Linux Widget Types like GTK. Here I suppose a documentation is lacking and thus only

As i understood PostMessage

PostMessage put the message in queue, the message received by window proc, so there is time between send this message and received, leave it to execute the code inside the MouseDown event.

In Windows it is managed by the system, i am reading the thread for that.

"user message" can be used, that

you receive in your own Pascal code (e.g. by procedure ... message). I know it is from old pascal.

Thanks

Zaher Dirkey -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20100507/848681c1/attachment.html>

Reply by email

Hans-Peter Diettrich
to Zaher Dirkey
Show quoted text 14 lines
When I said that the Windows documentation of PostMessage can be used, I did not think of the description of the messages to be sent by PostMessage. Same might be Windows-specific and in the LCL not ported (or portable) to Linux Widget Types like GTK. Here I suppose a documentation is lacking and thus only As i understood PostMessage PostMessage put the message in queue, the message received by window proc, so there is time between send this message and received, leave it to execute the code inside the MouseDown event. In Windows it is managed by the system, i am reading the thread for that.

Right, Windows manages messages and thus allows to send messages to other processes, and also can make the sender process or thread wait for an answer on SendMessage. When an OS doesn't support sending messages, the same handling can be implemented only inside a single application. Such an implementation can follow the Windows message format, where wParam and lParam can be pointers to local (process) data. In such cases the sender has to make sure that the related memory and all contained references stay valid, until the message has been handled by the receiver.

BTW, forms should never be free'd, instead Release should be used. Forms in released state will be free'd after they have processed all their queued messages.

DoDi

Reply by email

Michael Schnell
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote
Right, Windows manages messages...

Only the ones with message number lower that the "user" limit. Thus to do portable applications, only greater message numbers are allowed to be used with PostMessage. If a some GUI stuff needs to be triggered by a message in a portable way, you would not send the Windows-Message number and with that directly trigger the GUI system action by the thread (bypassing the LCL that is __supposed__ to manage the GUI actions), but send a message to the main thread and there (in the message handling procedure) do an LCL call that does the cation in the LCL-compatible way.

IMHO, even when doing just a Windows project, it's not recommended to bypass the LCL and send a Windows-message (lower than "user") via PorstMessage (or SendMessage) directly to the Windows GUI-System, as the LCL's internal state might not reflect that Windows GUI System state, and might do erroneous stuff later.

-Michael
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20100510/777d8d47/attachment.html>

Reply by email