Discussion:
Messages, Events & Threads
(too old to reply)
a***@aol.com
2010-09-08 08:14:23 UTC
Permalink
I think I'm asking a question about something I _should_ know <g>.

When a hardware or similar event occurs a message is sent to the
appropriate application. On receipt of such a message an event is
called and the code in the event handler is run.

Is the event, the message and the code in the event handler, run in
the application's thread or in the event's driver thread. Or does the
event's thread only post the message to the application's queue, and
the application's thread pulls it from the queue and process it when
it can.

How does one ensure that the next message received by the application
is processed only when the code in the event handler (and it's called
functions) are completed. And also process _all_ messages thar may be
posted.

In my application dropping the message (ie "lifting" the event handler
so that interim messages are ignored) is not an option, I must process
all messages received by the individual window (via it's separate
window handle). But I must handle messages only when the event
handler's code is completely finished.

Alan Lloyd
Jamie
2010-09-08 15:05:18 UTC
Permalink
Post by a***@aol.com
I think I'm asking a question about something I _should_ know <g>.
When a hardware or similar event occurs a message is sent to the
appropriate application. On receipt of such a message an event is
called and the code in the event handler is run.
Is the event, the message and the code in the event handler, run in
the application's thread or in the event's driver thread. Or does the
event's thread only post the message to the application's queue, and
the application's thread pulls it from the queue and process it when
it can.
How does one ensure that the next message received by the application
is processed only when the code in the event handler (and it's called
functions) are completed. And also process _all_ messages thar may be
posted.
In my application dropping the message (ie "lifting" the event handler
so that interim messages are ignored) is not an option, I must process
all messages received by the individual window (via it's separate
window handle). But I must handle messages only when the event
handler's code is completely finished.
Alan Lloyd
Each thread in your app needs to create a message loop. The OS has a
cache buffer for these messages (FIFO). As you loop through your message
loop in your app, one message is pulled out of the buffer for which you
process. Normally, this would be the "GetMessage" API, then you would
pass this to the "TranslateMessage" API to convert some messages like
the key board and mouse messages. Then you pass it to the
"DispatchMessage" API which then calls the window procedure belonging to
the message and thus, that handler receives (Form) the contents of this
message.. There are cases like Timers, where you can have it go directly
to a procedure instead of a Procedure of a Window handler (WinProcedure)..

When your window handles the message it should set the return flag
as "Handle"(Classes,Delphi Ect). Depending on how you want your program
to flow, in most cases you call the Default Window Handler in the end...

This is where Windows may do some stuff on it's own.. For example,
some menu controls where the background and designs are done default by
windows. This happens when you call the Default Window handler. If you
don't call this at the end of your Message Handler per window, windows
just assumes you have handled it and done what you wanted instead. But
in a lot of cases you call this regardless because your app may need the
notice of something windows is about to do and you want to do something
before it does... Like change a menu content to reflect a current
state!

At then end of this long haul, any messages you have no concern over
should just be past to the defWindow handler and allow your window
(form) procedure to exit which then, allows the "DepatchMessage" API in
your main loop to return. You then loop back to GetMessage for the next
message to pull out and repeat this process over.

Messages like WM_QUIT should be acted on and not looped back.

So, the only time you may have an issue with message collision is when
you are working 2 or more threads in your app that has a message cache
set up trying to perform some asynchronous handling between threads.


Jamie..
Hans-Peter Diettrich
2010-09-08 20:20:17 UTC
Permalink
Post by a***@aol.com
When a hardware or similar event occurs a message is sent to the
appropriate application. On receipt of such a message an event is
called and the code in the event handler is run.
Is the event, the message and the code in the event handler, run in
the application's thread or in the event's driver thread. Or does the
event's thread only post the message to the application's queue, and
the application's thread pulls it from the queue and process it when
it can.
I'd expect that (a sane implementation) would implement the message
queue inside the application (or thread) memory space, not in OS memory.
There also can exist multiple queues, with the most prominent for mouse
and paint events, where the events are accumulated in a dedicated place,
and true messages are generated only on request.

Regardless of the concrete implementation, the related procedures
(GetMessage, PeekMessage...) work on that queue(s) as documented.
Post by a***@aol.com
How does one ensure that the next message received by the application
is processed only when the code in the event handler (and it's called
functions) are completed. And also process _all_ messages thar may be
posted.
Every application is responsible for retrieving messages at the right
time, i.e. when it actually can respond to a message (e.g. when handling
of preceding message finished).
Post by a***@aol.com
In my application dropping the message (ie "lifting" the event handler
so that interim messages are ignored) is not an option, I must process
all messages received by the individual window (via it's separate
window handle). But I must handle messages only when the event
handler's code is completely finished.
PeekMessage allows to pick (and remove) certain messages from the queue,
so that multiple application/thread handlers can be designed to process
only certain messages (mouse, display...), and leave everything else to
other handlers. In order to make such a model work, the messages should
be sent via PostMessage, when they are intended for special
(asynchronous) processing; in this case the sender does not wait for
completion of the handler in the application. When the sender must be
sure that the application is in sync with the message generation, it can
use SendMessage, which call returns only after this concrete message
really has been processed.

DoDi
Maarten Wiltink
2010-09-08 20:16:15 UTC
Permalink
Post by a***@aol.com
I think I'm asking a question about something I _should_ know <g>.
When a hardware or similar event occurs a message is sent to the
appropriate application. On receipt of such a message an event is
called and the code in the event handler is run.
I think you're confusing two very different things here. You appear
to be talking about Windows _messages_ and Delphi _events_. If not,
I will be talking nonsense in the next paragraphs. Oh well, it's
happened before.

Windows messages originate somewhere and are appended to a queue.
A message loop processes the messages on the queue in order. It does
this with what amounts to a big case statement inside a loop. Per
thread, at most one message loop is running. This already ensures
that messages are always processed completely and in order.

A Delphi class may implement a message loop, and handle Windows
messages by firing Delphi events. If this calls a handler, it will
run. While the handler runs, nothing else is running, so the message
loop is stalled, too. When the handler returns, the message loop
can continue. Messages are still processed completely and in order.
So are events.

Windows messages have a very different feel from Delphi events
because Delphi appears to shield you from the source of events,
while most people experience Windows messages as things that come
from a defined place, a queue, and are processed much more explicitly,
'pull'-style, by running a loop to extract and handle them. In truth,
the queue does not produce messages, it only stores them, but doing
so it makes it _really_ impossible to tell where a message was posted
from, while Delphi events on the other hand are always fired from
somewhere, synchronously, without being kept on a queue in between -
so you can always trace back where it came from. Of course, a large
and important category of events is fired in order to handle a message
that came from a queue; the synchronicity breaks down there.
Post by a***@aol.com
Is the event, the message and the code in the event handler, run in
the application's thread or in the event's driver thread. Or does the
event's thread only post the message to the application's queue, and
the application's thread pulls it from the queue and process it when
it can.
Windows has things named events, too, and here it looks like you may
be talking about them and not Delphi events and their handlers.

A Windows event can occur and place a message on a queue. The queue
may be consumed by a different thread than the one that posted the
message. This is in fact a common way for threads to communicate.
Post by a***@aol.com
How does one ensure that the next message received by the application
is processed only when the code in the event handler (and it's called
functions) are completed. And also process _all_ messages thar may be
posted.
By not calling Application.ProcessMessages.

As I tried to explain above, event handlers are already a synchronous
mechanism. Don't mess with it and the worst that can happen is that
your application is momentarily unresponsive. It seems to be possible
to fill up your message queue but I've never heard of it actually
happening.
Post by a***@aol.com
In my application dropping the message (ie "lifting" the event handler
so that interim messages are ignored) is not an option, I must process
all messages received by the individual window (via it's separate
window handle). But I must handle messages only when the event
handler's code is completely finished.
If you're tempted to temporarily disconnect the event handler, you're
probably calling ProcessMessages. It's very simple. Don't.

If this makes your application unuseable, move handling events of
that class to a worker thread. Give it its own event queue and process
those according to your requirements. No need to make it a Windows
message queue; a queue of Delphi objects will work just fine. However,
you will be working in a multithreaded environment then. That's the
price you pay, and it's not cheap (in development and debugging effort).
Decoupling through that queue should help, though.

Groetjes,
Maarten Wiltink
a***@aol.com
2010-09-09 08:10:49 UTC
Permalink
Thank-you all, for some really helpful info & comment.

On 8 Sep, 21:16, "Maarten Wiltink" <***@kittensandcats.net> wrote:
<snip>
Post by Maarten Wiltink
I think you're confusing two very different things here. You appear
to be talking about Windows _messages_ and Delphi _events_. If not,
I will be talking nonsense in the next paragraphs. Oh well, it's
happened before.
Windows messages originate somewhere and are appended to a queue.
A message loop processes the messages on the queue in order. It does
this with what amounts to a big case statement inside a loop. Per
thread, at most one message loop is running. This already ensures
that messages are always processed completely and in order.
A Delphi class may implement a message loop, and handle Windows
messages by firing Delphi events. If this calls a handler, it will
run. While the handler runs, nothing else is running, so the message
loop is stalled, too. When the handler returns, the message loop
can continue. Messages are still processed completely and in order.
So are events.
Windows messages have a very different feel from Delphi events
because Delphi appears to shield you from the source of events,
while most people experience Windows messages as things that come
from a defined place, a queue, and are processed much more explicitly,
'pull'-style, by running a loop to extract and handle them. In truth,
the queue does not produce messages, it only stores them, but doing
so it makes it _really_ impossible to tell where a message was posted
from, while Delphi events on the other hand are always fired from
somewhere, synchronously, without being kept on a queue in between -
so you can always trace back where it came from. Of course, a large
and important category of events is fired in order to handle a message
that came from a queue; the synchronicity breaks down there.
<snip>
<

I think I was not completely clear on my message dependant system.

The hardware concerned is a USB three-pedal foot switch which has its
own "driver" (ie the access code to pass event info to user code) in a
dll. This is initialised by passing a window handle in an
initialisation call. I use Delphi's AllocHwnd() function to obtain a
handle to a zero-size window, specifying a message handling function
(which implements the message-handling loop case statement). Each
action (individual pedal down or pedal up) sends a message to the
supplied window handle. Each message generates calls to code handling
sound wave file content. There are reports (random by PC) that one of
the pedal-up actions is missed or inhibited.

Arising from Maarten's description of the message queueing mechanism,
my question would be "does AllocHwnd have a message-queueing
mechanism, or does the OS Send/Post Message mechanism invoked by the
"driver" inherently have one, or would the "driver" dll have one (I
don't know as its supplied by Olympus), or do I have to implement my
own queueing mechanism (& how do I readily do that).

Thanks

Alan Lloyd
Jamie
2010-09-09 12:16:24 UTC
Permalink
Post by a***@aol.com
Thank-you all, for some really helpful info & comment.
<snip>
Post by Maarten Wiltink
I think you're confusing two very different things here. You appear
to be talking about Windows _messages_ and Delphi _events_. If not,
I will be talking nonsense in the next paragraphs. Oh well, it's
happened before.
Windows messages originate somewhere and are appended to a queue.
A message loop processes the messages on the queue in order. It does
this with what amounts to a big case statement inside a loop. Per
thread, at most one message loop is running. This already ensures
that messages are always processed completely and in order.
A Delphi class may implement a message loop, and handle Windows
messages by firing Delphi events. If this calls a handler, it will
run. While the handler runs, nothing else is running, so the message
loop is stalled, too. When the handler returns, the message loop
can continue. Messages are still processed completely and in order.
So are events.
Windows messages have a very different feel from Delphi events
because Delphi appears to shield you from the source of events,
while most people experience Windows messages as things that come
from a defined place, a queue, and are processed much more explicitly,
'pull'-style, by running a loop to extract and handle them. In truth,
the queue does not produce messages, it only stores them, but doing
so it makes it _really_ impossible to tell where a message was posted
from, while Delphi events on the other hand are always fired from
somewhere, synchronously, without being kept on a queue in between -
so you can always trace back where it came from. Of course, a large
and important category of events is fired in order to handle a message
that came from a queue; the synchronicity breaks down there.
<snip>
<
I think I was not completely clear on my message dependant system.
The hardware concerned is a USB three-pedal foot switch which has its
own "driver" (ie the access code to pass event info to user code) in a
dll. This is initialised by passing a window handle in an
initialisation call. I use Delphi's AllocHwnd() function to obtain a
handle to a zero-size window, specifying a message handling function
(which implements the message-handling loop case statement). Each
action (individual pedal down or pedal up) sends a message to the
supplied window handle. Each message generates calls to code handling
sound wave file content. There are reports (random by PC) that one of
the pedal-up actions is missed or inhibited.
Arising from Maarten's description of the message queueing mechanism,
my question would be "does AllocHwnd have a message-queueing
mechanism, or does the OS Send/Post Message mechanism invoked by the
"driver" inherently have one, or would the "driver" dll have one (I
don't know as its supplied by Olympus), or do I have to implement my
own queueing mechanism (& how do I readily do that).
Thanks
Alan Lloyd
assuming that you need to supply a window handle to the DLL for the
device to communicate back to you, it's using the standard windows
messaging system "PostMessage" how ever, it could be using SENDMESSAGE
which does not use the que in your main message loop or, it could be
obtaining the Window Procedure address and directly calling the window
handler. In all cases, it'll get there except if it's using the
PostMessage! If the system gets congested, non important messages can
get purged or, the driver code for the device maybe ignoring this pile
up or, the driver code is using a message value that is conflicting with
other message values being used for something else that is going on..


Either way, it must return before another message is sent. The only
thing I see happening is maybe you're processing too much info in a
call and it's getting timed out by the USB device driver/DLL.

You may want to create a FIFO buffer in your window handler and use
a secondary thread to process the messages or use a secondary thread as
the window for your device and have the main thread process it etc..

Also, the problem may not be yours.. it could be a problem with
sound system initialization between calls on various PC's that is
causing hardware level hiccups, especially if USB sound devices are in
use on USB hubs. etc..


You don't say to what extend what kind of sound processing you're
doing and how deep you're getting into it... ? You may want to have a
handle opened to the sound system at all times while this is going on..



Jamie.
Maarten Wiltink
2010-09-09 13:16:53 UTC
Permalink
my question would be "does AllocHwnd have a message-queueing mechanism,
I think it gives you the queue. By its name, it allocates a window
handle, which is mostly useful as a thing to post messages to. They
have to go somewhere; it seems reasonable Windows takes care of that.

Not the message loop. But you mentioned having that already.
or does the OS Send/Post Message mechanism invoked by the "driver"
inherently have one,
Send- and PostMessage are simply WinAPI procedures. Since they take
a window handle as their first parameter, if that handle by its nature
can accept and store messages, the procedures can leave it at that.

Groetjes,
Maarten Wiltink
a***@aol.com
2010-09-09 19:44:35 UTC
Permalink
Thanks again for all your help.

I have done what I should have done to start with if I'd not been idle
<g>. I wrote a test program which displayed the events execution as
indicators & listbox entries, and put a Sleep(500) in one of the event
handlers. Hit the pedal five times as quick as I could (less than two
seconds) and after about ten seconds all the ten events (PedalDown &
PedalUp) appeared in the listbox.

So someone somewhere has a queue for the messages.

Alan Lloyd

Loading...