Sign in Join

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

Mailing lists / lazarus / 2014-03

Windows.PostMessage vs Application.QueueAsyncCall

38 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

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

Marcos Douglas

Hi,

Like all Windows programmer, I use PostMessage/SendMessage a lot. Lazarus team has created Application.QueueAsyncCall method to substitute the (old) "Windowish" method todo async calls aka PostMessage.

Ok. But what is the best way to use QueueAsyncCall when the caller to not knows what type is the receiver?

PostMessage only need to know a Handler and a Integer (message). It can send a broadcast message as well.

QueueAsyncCall need to know the instance and the method to call...

So, what the best way to substitute PostMessage?
Maybe using QueueAsyncCall + IFPObserved/IFPObserver?

Thanks,
Marcos Douglas

Reply by email

zeljko
to Marcos Douglas
Marcos Douglas wrote 18 lines
Hi, Like all Windows programmer, I use PostMessage/SendMessage a lot. Lazarus team has created Application.QueueAsyncCall method to substitute the (old) "Windowish" method todo async calls aka PostMessage. Ok. But what is the best way to use QueueAsyncCall when the caller to not knows what type is the receiver? PostMessage only need to know a Handler and a Integer (message). It can send a broadcast message as well. QueueAsyncCall need to know the instance and the method to call... So, what the best way to substitute PostMessage? Maybe using QueueAsyncCall + IFPObserved/IFPObserver?

Why you must substitute PostMessage ? I'm using PostMessage successfully for inter-thread communication,also I'm using QueueAsyncCall when I want to delay something eg. in OnShow of form ...

zeljko

Reply by email

Michael Schnell
to Marcos Douglas: Like all Windows programmer, I use PostMessage/SendMessage a lot. Lazarus team has…
Marcos Douglas wrote 7 lines
Like all Windows programmer, I use PostMessage/SendMessage a lot. Lazarus team has created Application.QueueAsyncCall method to substitute the (old) "Windowish" method todo async calls aka PostMessage. Ok. But what is the best way to use QueueAsyncCall when the caller to not knows what type is the receiver?

As QueueAsyncCall does not exist in Delphi you might want to avoid it to stay Delphi compatible.

So you can use TThread.Queue that is available both in Delphi (even though undocumented in some older versions) and in Lazarus/fpc (even though only in the not too old versions).

QueueAsyncCall need to know the instance and the method to call...

QueueAsyncCall is given the procedure to call and a parameter for same, but no "instance". TThread.Queue only gets the (parameter-less) procedure to call.

-Michael

Reply by email

zeljko
to Michael Schnell: As QueueAsyncCall does not exist in Delphi you might want to avoid it to stay Delphi…
Michael Schnell wrote 10 lines
On 03/16/2014 02:47 AM, Marcos Douglas wrote: > Like all Windows programmer, I use PostMessage/SendMessage a lot. > Lazarus team has created Application.QueueAsyncCall method to > substitute the (old) "Windowish" method todo async calls aka > PostMessage. > > Ok. But what is the best way to use QueueAsyncCall when the caller to > not knows what type is the receiver? As QueueAsyncCall does not exist in Delphi you might want to avoid it to stay Delphi compatible.

I don't care about Delphi compatibility in any case (in my applications).I'm using Lazarus and don't have any plan to use any commercial developer tool in the future. :)

So you can use TThread.Queue that is available both in Delphi (even though undocumented in some older versions) and in Lazarus/fpc (even though only in the not too old versions).

No, I'll keep using QueueAsyncCall as it is because it satisfies my needs.

zeljko

Reply by email

Hans-Peter Diettrich
to Michael Schnell: This is a Windowish left-over and really alien regarding the OS-independent making of…
Show quoted text 6 lines
On 03/16/2014 09:23 AM, zeljko wrote: > > Why you must substitute PostMessage ? This is a Windowish left-over and really alien regarding the OS-independent making of the LCL (even though In fact the LCL even simulates PostMessage in Linux.

How would you handle keyboard and mouse input and painting in an application?

DoDi

Reply by email

Marcos Douglas
to Michael Schnell: As QueueAsyncCall does not exist in Delphi you might want to avoid it to stay Delphi…
Michael Schnell wrote 12 lines
On 03/16/2014 02:47 AM, Marcos Douglas wrote: > > Like all Windows programmer, I use PostMessage/SendMessage a lot. > Lazarus team has created Application.QueueAsyncCall method to > substitute the (old) "Windowish" method todo async calls aka > PostMessage. > > Ok. But what is the best way to use QueueAsyncCall when the caller to > not knows what type is the receiver? As QueueAsyncCall does not exist in Delphi you might want to avoid it to stay Delphi compatible.

I don't care about Delphi compatibility. Today I only use FPC/Lazarus.

Show quoted text 10 lines
So you can use TThread.Queue that is available both in Delphi (even though undocumented in some older versions) and in Lazarus/fpc (even though only in the not too old versions). > QueueAsyncCall need to know the instance and the method to call... QueueAsyncCall is given the procedure to call and a parameter for same, but no "instance". TThread.Queue only gets the (parameter-less) procedure to call.

Yes, but the QueueAsyncCall needs to know what procedure to call for a especific object (instance).
Of course you can "simulate" not to know which instance calling this procedure and the implementation will instanciate the especific class... adding complexity IMHO.

Using PostMessage you can send a broadcast.

Marcos Douglas

Reply by email

Michael Schnell
to Marcos Douglas
Marcos Douglas wrote
Yes, but the QueueAsyncCall needs to know what procedure to call for a especific object (instance)

I don't understand.

The definition of the function (I use) is

     procedure TApplication.QueueAsyncCall(const AMethod: TDataEvent;
Data: PtrInt);
                                      with
   TDataEvent = procedure (Data: PtrInt) of object;

I don't see an "instance" here.

-Michael

Reply by email

Marcos Douglas
to Michael Schnell
Michael Schnell wrote 19 lines
On 03/17/2014 01:31 PM, Marcos Douglas wrote: > > Yes, but the QueueAsyncCall needs to know what procedure to call for a > especific object (instance) I don't understand. The definition of the function (I use) is procedure TApplication.QueueAsyncCall(const AMethod: TDataEvent; Data: PtrInt); with TDataEvent = procedure (Data: PtrInt) of object; I don't see an "instance" here.

CASE 1:
You have MainForm (Main) and ProcessForm (Proc).
Proc do not know Main but Main needs to be updated about what happen in Proc so, Proc can use QueueAsyncCall that need a TDataEvent procedure as argument. If Proc not know Main, how he know the procedure (TDataEvent) to pass on argument?

Sugestion: I can Create Proc passing the procedure (TDataEvent) to call inside Proc.

CASE 2:
You have MainForm (Main), InfoForm (that have 2 Frames F1 and F2 that not know InfoForm) and ProcessForm (Proc).
Proc do not know Main, InfoForm or frames but they needs to be updated about what happen in Proc so, Proc can use QueueAsyncCall that need a TDataEvent procedure as argument. If Proc not know about these "Handlers", how he know the procedure (TDataEvent) to pass on argument?

I think that I need is too much for a simple call to QueueAsyncCall. I'm doing tests with FP Observer implementation too. Best regards, Marcos Douglas

Reply by email

Michael Schnell
to Marcos Douglas

On 03/17/2014 03:36 PM, Marcos Douglas wrote:

The pointer to the Event Procedure, the self pointer of it's instance (both denoted by "AMethod") and the pointer to the parameter to have it called with (denoted by"Data" are queued and when the main thread is ready to handle the event, it calls "AMethod" appropriately.

If you meant the self pointer of AMethod, I of course am with you (as same is a "procedure of object").

-Michael

Reply by email

Michael Schnell
to Michael Schnell
Michael Schnell wrote 5 lines
If you meant the self pointer of AMethod, I of course am with you (as same is a "procedure of object").

But that is rather trivial, and AMethod could be a procedure of any class (inducing but not forcing the "TThread" instance that schedules the call.

I think that I need is too much for a simple call to QueueAsyncCall. I'm doing tests with FP Observer implementation too.

A nice trick is to create an instance of a "data holding" object, fill it and provide it as "Data" with QueueAsyncCall. In the call you can free the "data holding" object.

Another trick that also works with TThread.Queue is to provide the data holding" class with a procedure, create and fill same and provide the procedure (including instance) with TThread.Queue. Here you need to take more care with freeing the object. I'm not sure if you simply can do "free;" as the last instruction before returning from the procedure.

-Michael

Reply by email

Michael Schnell
to Michael Schnell
Michael Schnell wrote
I'm not sure if you simply can do "free;" as the last instruction before returning from the procedure.

I just did a test and even this seems to work: An object seemingly can free itself and return to the caller of the function just as if this function would be another destructor.

-Michael

Reply by email

Marcos Douglas
to Michael Schnell: But that is rather trivial, and AMethod could be a procedure of any class (inducing but…
Michael Schnell wrote 17 lines
On 03/17/2014 04:09 PM, Michael Schnell wrote: > > > > If you meant the self pointer of AMethod, I of course am with you (as same > is a "procedure of object"). > But that is rather trivial, and AMethod could be a procedure of any class (inducing but not forcing the "TThread" instance that schedules the call. > I think that I need is too much for a simple call to QueueAsyncCall. > I'm doing tests with FP Observer implementation too. A nice trick is to create an instance of a "data holding" object, fill it and provide it as "Data" with QueueAsyncCall. In the call you can free the "data holding" object.

I do that today using PostMessage.
IMHO the problem in QueueAsyncCall, comparing with PostMessage, it is needs to know what procedure (method of an instance) to call to use on queue meanwhile PostMessage function just put a message on queue. The object that is listening for messages knows what procedure/method to execute itself.

Show quoted text 5 lines
Another trick that also works with TThread.Queue is to provide the data holding" class with a procedure, create and fill same and provide the procedure (including instance) with TThread.Queue. Here you need to take more care with freeing the object. I'm not sure if you simply can do "free;" as the last instruction before returning from the procedure.

I do not have problems using Threads but I don't use TThread.Queue. I just use TThread.Synchronize and this is works for me. I know TThread.Queue is new, but I never used... maybe you can explain me what advantages, please.

Regards,
Marcos Douglas

Reply by email

Marcos Douglas
to Michael Schnell: I just did a test and even this seems to work: An object seemingly can free itself and…
Michael Schnell wrote 8 lines
On 03/17/2014 04:20 PM, Michael Schnell wrote: > > I'm not sure if you simply can do "free;" as the last instruction before > returning from the procedure. > I just did a test and even this seems to work: An object seemingly can free itself and return to the caller of the function just as if this function would be another destructor.

Could you send the sources of this test?

Thanks,
Marcos Douglas

Reply by email

Michael Schnell
to Marcos Douglas
Marcos Douglas wrote
Could you send the sources of this test?

I could if you are interested.

This is a testing project I did for the development of Widget Types (with and without GUI Binding) on behalf of TThread.Synchronize, TThread.Queue, Application.QueueAsyncCall, and PostMessage.

-Michael

Reply by email

Marcos Douglas
to Michael Schnell
Michael Schnell wrote 10 lines
On 03/17/2014 05:42 PM, Marcos Douglas wrote: > > > Could you send the sources of this test? > I could if you are interested. This is a testing project I did for the development of Widget Types (with and without GUI Binding) on behalf of TThread.Synchronize, TThread.Queue, Application.QueueAsyncCall, and PostMessage.

I'm interested. Could you send for my mail, please? Thank you.

Marcos Douglas

Reply by email

Marcos Douglas
to Joao Morais
Joao Morais wrote 7 lines
Em 15/03/14 22:47, Marcos Douglas escreveu: > So, what the best way to substitute PostMessage? > Maybe using QueueAsyncCall + IFPObserved/IFPObserver? Have you tried decoupling your classes with interfaces?

I thought, yes, but I want to keep simple as possible.

If I understood your scenario correctly: Main implements an interface known by Proc, which sends itself to the Proc constructor.

That's an idea... but isn't like that today. Proc (following example) do not know Main or any interface that Main knows. Proc could be used in many others classes and not knows nothing about these classes.

Using PostMessage Proc just notify "handlers" about a message with the possibility to send "value objects" too.

Regards,
Marcos Douglas

Reply by email

Joao Morais
to Marcos Douglas
Marcos Douglas wrote 8 lines
On Mon, Mar 17, 2014 at 3:12 PM, Joao Morais wrote: > Em 15/03/14 22:47, Marcos Douglas escreveu: > >> So, what the best way to substitute PostMessage? >> Maybe using QueueAsyncCall + IFPObserved/IFPObserver? > > Have you tried decoupling your classes with interfaces? I thought, yes, but I want to keep simple as possible.

Simplicity and portability - two arguments on behalf of interfaces! =)

Show quoted text 7 lines
> If I understood your > scenario correctly: Main implements an interface known by Proc, which sends > itself to the Proc constructor. That's an idea... but isn't like that today. Proc (following example) do not know Main or any interface that Main knows. Proc could be used in many others classes and not knows nothing about these classes.

Because of that Proc only knows an interface that Main, perhaps others should implement.

Anyway just thinking out loud, you are the one that knows the requisites, what can and what can't be done. =)

HTH

Reply by email

Sven Barth
to Hans-Peter Diettrich: How would you handle keyboard and mouse input and painting in an application? DoDi
"Hans-Peter Diettrich" wrote 9 lines
Michael Schnell schrieb: > On 03/16/2014 09:23 AM, zeljko wrote: >> >> >> Why you must substitute PostMessage ? > > This is a Windowish left-over and really alien regarding the

OS-independent making of the LCL (even though In fact the LCL even simulates PostMessage in Linux.

How would you handle keyboard and mouse input and painting in an

application?

Like any other widgetset which does know nothing about PostMessage does?

Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20140317/256a5b02/attachment.html>

Reply by email

Michael Schnell
to Hans-Peter Diettrich: How would you handle keyboard and mouse input and painting in an application? DoDi
Hans-Peter Diettrich wrote 7 lines
Michael Schnell schrieb: > This is a Windowish left-over and really alien regarding the > OS-independent making of the LCL (even though In fact the LCL even > simulates PostMessage in Linux. How would you handle keyboard and mouse input and painting in an application?

AFAIK, this is not supported by the PostMessage implementation in the LCL in Linux.

So it in fact is a Windowish left-over.

-Michael

Reply by email

Michael Schnell
to Sven Barth: OS-independent making of the LCL (even though In fact the LCL even simulates PostMessage…
Sven Barth wrote 11 lines
Am 17.03.2014 19:15 schrieb "Hans-Peter Diettrich" < <mailto:>>: > > How would you handle keyboard and mouse input and painting in an application? Like any other widgetset which does know nothing about PostMessage does?

AFAIK, all "decent" (with event queue, in fact all that support "painting") Widget Types that are implemented in the LCL do provide PostMessage for thread -> MainThread notification (but not for keyboard and mouse input and painting issues).

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

Reply by email

Hans-Peter Diettrich
to Michael Schnell: AFAIK, this is not supported by the PostMessage implementation in the LCL in Linux. So it…
Show quoted text 10 lines
On 03/17/2014 11:22 AM, Hans-Peter Diettrich wrote: > Michael Schnell schrieb: >> This is a Windowish left-over and really alien regarding the >> OS-independent making of the LCL (even though In fact the LCL even >> simulates PostMessage in Linux. > > How would you handle keyboard and mouse input and painting in an > application? AFAIK, this is not supported by the PostMessage implementation in the LCL in Linux.

The LCL is based on the message queue, regardless of any OS or widgetset. PostMessage is part of the message queue.

So it in fact is a Windowish left-over.

You didn't answer my question: which other event handling model would you prefer, for use on any target and widgetset?

DoDi

Reply by email

Michael Schnell
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote
The LCL is based on the message queue, regardless of any OS or widgetset. PostMessage is part of the message queue.

Yep. (Even though I prefer the term "Event Queue" as the queued information this is not necessarily similar to Windowish "Messages".)

In fact there is an Event Queue in the RTL (that is used e.g. for TThread.xxx based events) and an additional Event Queue that handles events based on the GUI the LCL binds to (here the Events are "Messages" if the GUI is Windows). With Windows, the Queue itself is implemented in the OS and only _used_ in the LCL, while with any Linux GUIs, the queue is implemented in the LCL and is fed by Events _generated_ by the GUI (no idea about Mac). Now, the GUI-attaching "Widget Type" implementations in the LCL merge the events of both queues, while the not GUI-attaching Widget types currently even ignore the RTL based queue.

You didn't answer my question: which other event handling model would you prefer, for use on any target and widgetset?

Because I don't understand the your meaning here.

- I personally would prefer TThread.Synchronize and TThread.Queue because both are usable in Delphi, too, and provide as well blocking (.Synchronize) and non-blocking (.Queue) mode with identical syntax.

- QueueAsyncCall has it's point, as it's easy to transfer a (queued) parameter to the procedure. With TThread.Queue, this is more effort, as you need to make the synchronized procedure part of a class you install an instance of before sending it to the main thread via TThread.Queue, and later, the instance of course needs to be freed (this seems to be possible in the synchronized procedure itself just before returning)

- I don't understand what you intend by mentioning the "mouse input and painting" issue.

-Michael

Reply by email

Hans-Peter Diettrich
to Michael Schnell
Show quoted text 6 lines
On 03/18/2014 09:57 AM, Hans-Peter Diettrich wrote: > > The LCL is based on the message queue, regardless of any OS or > widgetset. PostMessage is part of the message queue. Yep. (Even though I prefer the term "Event Queue" as the queued information this is not necessarily similar to Windowish "Messages".)

The message queue is not restricted to events.

Show quoted text 7 lines
In fact there is an Event Queue in the RTL (that is used e.g. for TThread.xxx based events) and an additional Event Queue that handles events based on the GUI the LCL binds to (here the Events are "Messages" if the GUI is Windows). With Windows, the Queue itself is implemented in the OS and only _used_ in the LCL, while with any Linux GUIs, the queue is implemented in the LCL and is fed by Events _generated_ by the GUI (no idea about Mac).

Yes, events fit nicely into a message queue.

The events, created by the window manager and other OS services, must find their way to the component and user handlers, what in most widgetsets is done by calling dedicated callback functions. The parameter lists and events must be unified, so that the LCL can provide a common interface for all user supplied handlers. What's so bad in using the Windows messages for that purpose, and what would be your other way of doing that?

Now, the GUI-attaching "Widget Type" implementations in the LCL merge the events of both queues, while the not GUI-attaching Widget types currently even ignore the RTL based queue.

What's "GUI-attaching"?

> You didn't answer my question: which other event handling model would > you prefer, for use on any target and widgetset? Because I don't understand the your meaning here.

Do you understand events at all, their implementation and handling?

[...]

- I don't understand what you intend by mentioning the "mouse input and painting" issue.

Then try to explain how e.g. a key or button press event is processed in your model.

DoDi

Reply by email

Marcos Douglas
to Joao Morais: Simplicity and portability - two arguments on behalf of interfaces! =) Because of that…
Joao Morais wrote 16 lines
Em 17/03/14 16:28, Marcos Douglas escreveu: > On Mon, Mar 17, 2014 at 3:12 PM, Joao Morais wrote: >> >> Em 15/03/14 22:47, Marcos Douglas escreveu: >> >>> So, what the best way to substitute PostMessage? >>> Maybe using QueueAsyncCall + IFPObserved/IFPObserver? >> >> >> Have you tried decoupling your classes with interfaces? > > I thought, yes, but I want to keep simple as possible. Simplicity and portability - two arguments on behalf of interfaces! =)

Simplicity with interfaces, not always...

Why portability?

Show quoted text 16 lines
>> If I understood your >> scenario correctly: Main implements an interface known by Proc, which >> sends >> itself to the Proc constructor. > > That's an idea... but isn't like that today. Proc (following example) > do not know Main or any interface that Main knows. > Proc could be used in many others classes and not knows nothing about > these classes. Because of that Proc only knows an interface that Main, perhaps others should implement. Anyway just thinking out loud, you are the one that knows the requisites, what can and what can't be done. =)

The requisites isn't a secret: a form needs to notify many windows using asynchronous messages. PostMessage do that but some programmers say this is an old Windowish approach so, I'm searching another method to do the same PostMessage does and making the code more cross.

Regards,
Marcos Douglas

Reply by email

Michael Schnell
to Hans-Peter Diettrich: The message queue is not restricted to events. Yes, events fit nicely into a message…
Hans-Peter Diettrich wrote
Then try to explain how e.g. a key or button press event is processed in your model.

I don't have a "model". I just tried to describe what the LCL does.

You can see the multiple Queues in the source code:

- Queue in the fpc RTL that is fed by things like "TThread.Queue"
- Queue in the Linux GUI based LCL that is fed by events (such as Key or Mouse) generated by the WidgetSet it _attaches_ to (this defines is the "attach" word that I mentioned)
- Queue in the Windows OS the LCL in a Windows based Widget type attaches to (instead of implementing it's own event queue)

-Michael

Reply by email

Joao Morais
to Marcos Douglas: Simplicity with interfaces, not always... Why portability? The requisites isn't a secret:…
Marcos Douglas wrote
a form needs to notify many windows using asynchronous messages. PostMessage do that but some programmers say this is an old Windowish approach so, I'm searching another method to do the same PostMessage does and making the code more cross.

I missed the "async" part, sorry. What about reuse App.QueueAsyncCall with interface?

======>>>======

type
   IProcCallback = interface
     procedure ASync(data: ptrint);
   end;
   TProc = class(TObject)
   private
     FCallback: IProcCallback;
   public
     constructor Create(const ACallback: IProcCallback);
     procedure DoStuff;
   end;
constructor TProc.Create(const ACallback: IProcCallback);
begin
   inherited Create;
   FCallback := ACallback;
end;
procedure TProc.DoStuff;
begin
   //...
   Application.QueueAsyncCall(@FCallback.ASync, 0);
end;

======<<<======

You can also use {$interfaces corba} if you don't use objects with refcount.

Following this architecture, the responsible for creating TProc instance (let's say, TMain) needs to know someone that implements IProcCallback, which can be itself (TMain) of course. TMain knows TProc. TProc, TMain and others know IProcCallback, and IProcCallback doesn't know anyone.

Reply by email

Hans-Peter Diettrich
to Michael Schnell: I don't have a "model". I just tried to describe what the LCL does. You can see the…
Show quoted text 9 lines
On 03/18/2014 02:13 PM, Hans-Peter Diettrich wrote: > Then try to explain how e.g. a key or button press event is processed > in your model. I don't have a "model". I just tried to describe what the LCL does. You can see the multiple Queues in the source code: - Queue in the fpc RTL that is fed by things like "TThread.Queue"

This queue may be unusable for LCL messages (dunno).

Show quoted text 5 lines
- Queue in the Linux GUI based LCL that is fed by events (such as Key or Mouse) generated by the WidgetSet it _attaches_ to (this defines is the "attach" word that I mentioned) - Queue in the Windows OS the LCL in a Windows based Widget type attaches to (instead of implementing it's own event queue)

IMO these queues are equivalent, only the implementor (Windows/LCL) is different.

DoDi

Reply by email

Hans-Peter Diettrich
to Marcos Douglas: Simplicity with interfaces, not always... Why portability? The requisites isn't a secret:…
The requisites isn't a secret: a form needs to notify many windows using asynchronous messages. PostMessage do that but some programmers say this is an old Windowish approach so, I'm searching another method to do the same PostMessage does and making the code more cross.

A solution depends on the handling of your "asynchronous" messages. As long as the windows (forms?) exist in the same thread, all processing within this thread must be sequential (serialized). This can be achieved with a single queue.

When you want true asynchronous processing, implement an thread with its own queue that receives the asynchronous messages. Then you are free to implement your own message dispatcher in that thread.

You also can implement your own message dispatcher in the main thread, by implementing your own message loop. But then you risk to make the application temporarily unresponsive, when your asynchronous events are processed before UI messages.

Another solution may be an Idle message queue, and IMO something like that is implemented for QueueAsyncCall and OnIdle events. Then it depends on the message priority whether it is processed before (high priority) or after (idle state) UI messages, in the (existing/your) main thread dispatcher. Or you add an OnIdle handler to all target windows, or to the main window only, that looks for and processes the asynchronous events in a dedicated message queue, without blocking the UI.

For Windows applications you should eventually know some bits about the main thread message queue. Windows e.g. creates mouse move events when needed, but not for every single move; instead the message receives the *current* mouse position, when fetched from the queue. Similarly a WM_PAINT request is queued only when the message queue is empty, and while the update region is not empty. This assures that painting has the lowest priority amongst all messages in the main message queue. Some other messages are sent immediately to a window, bypassing the message queue. And last not least some Windows controls bypass (or peek?) the message queue as well, so that some standard events are never received by user supplied message handlers. At least I found such behaviour with messages related to painting an edit control.

DoDi

Reply by email

Marcos Douglas
to Joao Morais: I missed the "async" part, sorry. What about reuse App.QueueAsyncCall with interface?…
Joao Morais wrote 46 lines
Em 18/03/14 10:47, Marcos Douglas escreveu: > a form needs to notify many windows > using asynchronous messages. PostMessage do that but some programmers > say this is an old Windowish approach so, I'm searching another method > to do the same PostMessage does and making the code more cross. I missed the "async" part, sorry. What about reuse App.QueueAsyncCall with interface? ======>>>====== type IProcCallback = interface procedure ASync(data: ptrint); end; TProc = class(TObject) private FCallback: IProcCallback; public constructor Create(const ACallback: IProcCallback); procedure DoStuff; end; constructor TProc.Create(const ACallback: IProcCallback); begin inherited Create; FCallback := ACallback; end; procedure TProc.DoStuff; begin //... Application.QueueAsyncCall(@FCallback.ASync, 0); end; ======<<<====== You can also use {$interfaces corba} if you don't use objects with refcount. Following this architecture, the responsible for creating TProc instance (let's say, TMain) needs to know someone that implements IProcCallback, which can be itself (TMain) of course. TMain knows TProc. TProc, TMain and others know IProcCallback, and IProcCallback doesn't know anyone.

Ok, this is a good idea -- I'm implementing using concrete classes -- to minimize dependencies... but I still need using an Observer pattern here because I need a "broadcast message" for many objects.

IMHO there is a "design problem" in PostMessage or QueueAsyncCall: They are using a Pointer to pass arguments -- pointer or PtrInt as the same. The caller -- using PostMessage or QueueAsyncCall, doesn't matter -- doesn't know what valid argument that the receiver will accept. The programmer could send a Record instance, Object, Integer, whatever. This is not good. Here using interfaces is good: Encapsulate the Async(AData: PtrInt) in a interface to each class implement your own code to (a)sync.

Regards,
Marcos Douglas

Reply by email

Marcos Douglas
to Hans-Peter Diettrich: A solution depends on the handling of your "asynchronous" messages. As long as the…
Hans-Peter Diettrich wrote 30 lines
Marcos Douglas schrieb: > The requisites isn't a secret: a form needs to notify many windows > using asynchronous messages. PostMessage do that but some programmers > say this is an old Windowish approach so, I'm searching another method > to do the same PostMessage does and making the code more cross. A solution depends on the handling of your "asynchronous" messages. As long as the windows (forms?) exist in the same thread, all processing within this thread must be sequential (serialized). This can be achieved with a single queue. When you want true asynchronous processing, implement an thread with its own queue that receives the asynchronous messages. Then you are free to implement your own message dispatcher in that thread. You also can implement your own message dispatcher in the main thread, by implementing your own message loop. But then you risk to make the application temporarily unresponsive, when your asynchronous events are processed before UI messages. Another solution may be an Idle message queue, and IMO something like that is implemented for QueueAsyncCall and OnIdle events. Then it depends on the message priority whether it is processed before (high priority) or after (idle state) UI messages, in the (existing/your) main thread dispatcher. Or you add an OnIdle handler to all target windows, or to the main window only, that looks for and processes the asynchronous events in a dedicated message queue, without blocking the UI.

The app do not need these sophistications (for now), it needs to be strong at the first place and I do not want to have problems with synchronization between threads at this moment. However I like your ideas... to the future.

Show quoted text 11 lines
For Windows applications you should eventually know some bits about the main thread message queue. Windows e.g. creates mouse move events when needed, but not for every single move; instead the message receives the *current* mouse position, when fetched from the queue. Similarly a WM_PAINT request is queued only when the message queue is empty, and while the update region is not empty. This assures that painting has the lowest priority amongst all messages in the main message queue. Some other messages are sent immediately to a window, bypassing the message queue. And last not least some Windows controls bypass (or peek?) the message queue as well, so that some standard events are never received by user supplied message handlers. At least I found such behaviour with messages related to painting an edit control.

Thanks for the tips.

Regards,
Marcos Douglas

Reply by email

Michael Schnell
to Hans-Peter Diettrich: This queue may be unusable for LCL messages (dunno). IMO these queues are equivalent,…
Hans-Peter Diettrich wrote
This queue may be unusable for LCL messages (dunno).

It _is_ used for the said purpose, simply because the TThread class is provided by the fpc RTL (not the LCL) and here it can't do other but feed the Queue in the RTL. And this obviously works just fine (at least with Windows and Linux "GTK2", I did not decently other GUI enabled Widget Types).

Show quoted text 7 lines
> - Queue in the Linux GUI based LCL that is fed by events (such as > Key or Mouse) generated by the WidgetSet it _attaches_ to (this > defines is the "attach" word that I mentioned) > - Queue in the Windows OS the LCL in a Windows based Widget type > attaches to (instead of implementing it's own event queue) IMO these queues are equivalent, only the implementor (Windows/LCL) is different.

Regarding the "normal" GUI events you are right.
But in Windows this queue can be used for other stuff, too, such as sending messages directly to Windows control elements and doing inter-Process (instead internal thread-to-Mainthread) signaling.

-Michael

Reply by email

Michael Schnell
to Joao Morais: I missed the "async" part, sorry. What about reuse App.QueueAsyncCall with interface?…
Joao Morais wrote
I missed the "async" part, sorry. What about reuse App.QueueAsyncCall with interface?

Combining the Interface idea with asynchronous signaling in fact is a nice idea.

The real issue is that in many cases you need to queue not only the call but the parameters for the call as well.

Here we have:

- TThread.Queue only calls the call (but of course this is the procedure address and the "self" of the instance you use in the argument when calling TThread.Queue
- Application.QeueAsyncCall additionally takes a pointer as a parameter that is queued and when scheduled given to the signaled procedure called in the main thread

But obviously it can be necessary to queue more information than just a pointer.

I did a testing program using TThread.Queue.

I defined a "TData" class that contains the data and a procedure with no parameter.

When placing the event, in the worker Thread do:
- create an instance of the TData" class, just storing the reference in a local variable " Data: TData; "Data := TData.Create; " ("Data" funnily is long forgotten when the call in fact is scheduled in the main thread)
- Fill "Data" with the data to be worked on in the main thread
- do " Queue(Data.QueuedCall); "

Now some time later the call is scheduled in the main thread and QueuedCall starts running.
- You can correctly access all data in this instance of the TData class. Any other work in the WorkerThread would have created a new independent instance of same
- After doing what needs to be done you just do " free; " as the last line of the QueuedCall procedure. Here the current instance it works on is freed. This does not (seem to) be a problem, as after the free you return to completely unrelated stuff.

I am not experienced with Interfaces, but I do know that interfaces can create and free class instances automatically "under the hood", and hence it might be better programming style to use same instead o manually do a " Create " and " Free; " in user code.

If it would be possible to do such an interface driven thingy in a library in a way that the actual structure of the data can be defined in user code, this would be a great addition (IMHO better for the RTL than for the LCL).

-Michael

Reply by email

Martin Schreiber
to Michael Schnell
Michael Schnell wrote
The real issue is that in many cases you need to queue not only the call but the parameters for the call as well.

Maybe have a look how it is done in MSEgui with tmseevent/tobjectevent, application.postevent() and friends? IIRC you already played with them?

Martin

Reply by email

Michael Schnell
to Hans-Peter Diettrich: A solution depends on the handling of your "asynchronous" messages. As long as the…
Hans-Peter Diettrich wrote
For Windows applications you should eventually know some bits about the main thread message queue.

Not really, as LCL and RTL provide as well TThread.Queue and Application.QueueAsyncCall in Windows and Linux (and Mac, AFAIK). In Delphi you just have TThread.Queue. (Hence TThread.Queue in fact is my favorite way of asynchronous signaling. )

The "very old style" Delphi / Windows way for asynchronous signaling was using " PostMessage(); "and "Procedure ....message .. ".

We poor Delphi programmers were forced to do this before Borland and friends implemented " TThread.Queue() ". In fact they were bold enough to provide the documentation for TThread.Queue only several versions later than the actually working implementation.

-Michael

Reply by email

Michael Schnell
to Martin Schreiber: Maybe have a look how it is done in MSEgui with tmseevent/tobjectevent,…
Martin Schreiber wrote
Maybe have a look how it is done in MSEgui with tmseevent/tobjectevent, application.postevent() and friends? IIRC you already played with them?

:-) :-) :-)

Yep ! I do like this stuff !

On behalf of OS and Widget-Set independent and user friendly thread handling MSE is a lot more advanced than Lazarus, because id did not need to take Delphi compatibility into account.

-Michael

Reply by email