Windows Form Message Loop

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Would I be correct in saying that the only way to get a user message into a
Windows form would be to use P/Invoke with [Send/Post]Message?

Of is there some part of the .NET API that I am totally un aware of?

Thanks for any help
Brian
 
the message basically is a string for the window to display,
I want to use the loop because in want to implement a prioritised message
loop, i.e., handle any windows message first then handle my user message.

Reason: My user messages will be coming v.fast, So I want to enforce
processing of any windows messages before processing my user message.

thanks
Brian

Patrik Löwendahl said:
Depends on what you want the message to do and why you want it in the loop?

--
Patrik Löwendahl [C# MVP]
cshrp.net - 'Elegant code by witty programmers'
cornerstone.se 'IT Training for professionals'
Would I be correct in saying that the only way to get a user message into a
Windows form would be to use P/Invoke with [Send/Post]Message?

Of is there some part of the .NET API that I am totally un aware of?

Thanks for any help
Brian
 
Seems like you are not completely clear how windows messages are handled in
Windows (Win32) and as such Windows.Forms.

Consider the example you posted recently:
In this you have:
- a main thread handling the UI and,
- two worker threads (called workers), handling external communication and
dispatching messages (Text) to the UI thread.

Because the workers may not directly touch the UI thread affinitized window
handles, you correctly opted to use Control.Invoke to marshal the delegate
to the UI thread.
What basically happens when you call Invoke is :
- Put a Thread Method Entry object in a Linked list ( a queue), this TME
contains things like caller, target HWND, method delegate, arguments, the
compressed caller stack etc.
- Post a private USER Windows message (calling Win32 PostMessage) to the UI
thread application message queue.
- Wait for an Event that signals the end of the delegate method. (This is
what differentiates BeginInvoke from Invoke, in that BeginInvoke doesn't
wait but returns immediately)

When the UI thread message loop retrieves the private USER message from it's
application "message queue" in it's message handler, it also pulls the TME
from the linked list and executes the TME's method(function, eventhandler
etc..) on it's own thread (UI) using the arguments supplied and the
compressed caller stack. Whenever the method returns, the message handler
set's an Event signaling the caller that a method ran to completion. and
continues handling next application message.

If there's no further message in the UI thread's application message queue
(no further Posted messages), the Windows system will inspect the "input
message" queue and switch the message loop to this queue if there are input
messages (mouse, keyboard), however, as soon as there are new messages in
the application queue Windows will switch back to this queue for its message
processing. [note that not all input messages are placed in the input
queue!!]
What this all means is that Windows queues are prioritized by windows, that
means that posted messages have higher priority than input messages, and as
long as there are posted messages, no input messages (mouse clicks f.i) are
getting process. Worse, input messages are processed one at a time, that
means that a key-down event can be handled before a bunch of posted messages
followed by the handling of the key-up event.
To you it means that you should allow the message queue to drain at regular
intervals in order to allow input messages to be processed.
Now I still wonder why someone is placing all this stuff on the screen,
while I see hardly someone reading this at this speed.

Willy.


Brian Keating EI9FXB said:
Would I be correct in saying that the only way to get a user message into
a
Windows form would be to use P/Invoke with [Send/Post]Message?

Of is there some part of the .NET API that I am totally un aware of?

Thanks for any help
Brian
 
Hi Willy,

I'd a look at the messages coming through the WndProc this morning and
noticed this user message in response to the Invoke.
Your explanation has cleared up what exactly happens in response to a
..Invokexxx,
Also you've really opened my eyes with the "Input quque" this explains why
my input message are not getting handled.

Also at the end of your post you wonder about how quick someone can read,
you are quite correct; but consider an applicationt that writes quite alot to
the screen for one minute then goes off and idles for a while, the user can
scroll back along the messages that were outputed to the screen to see what
exactly happened.

However I think I know what you are getting at, and as also suggested by Ian
Griffiths, it makes alot more sence to update the UI at a refresh interval,
and display any new messages.

Thanks for your reply, I'm starting to see things alot more clearly.
best regards
Brian.

Willy Denoyette said:
Seems like you are not completely clear how windows messages are handled in
Windows (Win32) and as such Windows.Forms.

Consider the example you posted recently:
In this you have:
- a main thread handling the UI and,
- two worker threads (called workers), handling external communication and
dispatching messages (Text) to the UI thread.

Because the workers may not directly touch the UI thread affinitized window
handles, you correctly opted to use Control.Invoke to marshal the delegate
to the UI thread.
What basically happens when you call Invoke is :
- Put a Thread Method Entry object in a Linked list ( a queue), this TME
contains things like caller, target HWND, method delegate, arguments, the
compressed caller stack etc.
- Post a private USER Windows message (calling Win32 PostMessage) to the UI
thread application message queue.
- Wait for an Event that signals the end of the delegate method. (This is
what differentiates BeginInvoke from Invoke, in that BeginInvoke doesn't
wait but returns immediately)

When the UI thread message loop retrieves the private USER message from it's
application "message queue" in it's message handler, it also pulls the TME
from the linked list and executes the TME's method(function, eventhandler
etc..) on it's own thread (UI) using the arguments supplied and the
compressed caller stack. Whenever the method returns, the message handler
set's an Event signaling the caller that a method ran to completion. and
continues handling next application message.

If there's no further message in the UI thread's application message queue
(no further Posted messages), the Windows system will inspect the "input
message" queue and switch the message loop to this queue if there are input
messages (mouse, keyboard), however, as soon as there are new messages in
the application queue Windows will switch back to this queue for its message
processing. [note that not all input messages are placed in the input
queue!!]
What this all means is that Windows queues are prioritized by windows, that
means that posted messages have higher priority than input messages, and as
long as there are posted messages, no input messages (mouse clicks f.i) are
getting process. Worse, input messages are processed one at a time, that
means that a key-down event can be handled before a bunch of posted messages
followed by the handling of the key-up event.
To you it means that you should allow the message queue to drain at regular
intervals in order to allow input messages to be processed.
Now I still wonder why someone is placing all this stuff on the screen,
while I see hardly someone reading this at this speed.

Willy.


Brian Keating EI9FXB said:
Would I be correct in saying that the only way to get a user message into
a
Windows form would be to use P/Invoke with [Send/Post]Message?

Of is there some part of the .NET API that I am totally un aware of?

Thanks for any help
Brian
 
Would I be correct in saying that the only way to get a user message into a
Windows form would be to use P/Invoke with [Send/Post]Message?

Strictly, yes. Conceptually, no.
What I mean by "conceptually, no" is, if the thing emitting the 'message' is
part of the same .NET program as the windows form but in a different thread,
then the best way of getting a 'message' to the form is not to use an
*actual* message, but to use BeginInvoke, with a delegate, as I believe
others have pointed out. This is the recommended way of posting a 'message'
from a worker thread back to the user interface, and there will be lots of
examples of it, should you need them.
What I mean by "strictly, yes" is that if you're defining 'message' as an
*actual windows message*, i.e. WM_*, and the communication *must* be by this
means, then AFAIK the only way to get it to the form is to use PostMessage or
SendMessage.
Of is there some part of the .NET API that I am totally un aware of?

If you want to process custom messages, look into the following override,
that a form has:
public override bool PreProcessMessage(ref Message msg)
 
the message basically is a string for the window to display,
I want to use the loop because in want to implement a prioritised message
loop, i.e., handle any windows message first then handle my user message.

If you really need this to happen, then I believe the only option will be to
rewrite the form in C, with a custom message pump. All windows have a message
pump that is basically similar to the following:

1 [start of loop] ) get the next message (using GetMessage) from the
operating system's queue for the application. If there aren't any messages,
the call blocks until there is one. If the message is WM_QUIT, quit the loop
and go to step 5.
2) "Translate" the message (using TranslateMessage), this 'translates' the
message (what it actually does I don't know, just know that you have to do
it). Also accelerator keys are translated into messages in this step.
3) Dispatch the message to the WndProc of the window it was intended for
(using DispatchMessage)
4) Go back to (1), the start of the loop
5) Return the wParam of the message as the return value of the function that
invoked the window

What this means essentially, is that a window's wndproc only gets messages
in sequence, it doesn't "prioritise" messages in any way or let you decide
which get processed first. The wndproc has no concept of what the next
message will be and no option of doing, either (or what the previous one was
come to that, unless it explicitly takes steps to remember it).
The bottom line is that if you want to prioritise messages, you will have to
cook up your own custom message pump, probably using PeekMessage and an array
of messages, but whether that's advisable / necessary, I wouldn't know.
It theoretically could be done - if you peek into the queue and there's one
of your custom messages there, then it stores it in an array until there
aren't any messages waiting (PeekMessage returns zero). If there *are* more
messages waiting, then you would Get them, and if they are your custom one,
store them in the array of waiting ones, and if they're not, then just
dispatch them as normal. When there's no more waiting, you dispatch any that
are in the array.
The only downside is that you *can't* do this in .NET!
You can subclass to take control of processing of messages, and replace the
wndproc's default handling of the message with your own, but you can't do
this with the message pump - it's too low-level, the fundamental basis of the
operation of the window. You've got to get your hands dirty and delve into
raw hardcore C.


Reason: My user messages will be coming v.fast, So I want to enforce
processing of any windows messages before processing my user message.

thanks
Brian

Patrik Löwendahl said:
Depends on what you want the message to do and why you want it in the loop?

--
Patrik Löwendahl [C# MVP]
cshrp.net - 'Elegant code by witty programmers'
cornerstone.se 'IT Training for professionals'
Would I be correct in saying that the only way to get a user message into a
Windows form would be to use P/Invoke with [Send/Post]Message?

Of is there some part of the .NET API that I am totally un aware of?

Thanks for any help
Brian
 
Now I still wonder why someone is placing all this stuff on the screen,
while I see hardly someone reading this at this speed.

I can think of several reasons:
a) programs that constantly spool a load of text, fast, look *cool*.
b) if it constantly spools a load of text there can be no doubt that it's
doing stuff.
c) you can read it faster if you know what it's likely to say. i.e, you
don't actually have to read it, so much as 'recognize' general textual
patterns.
d) if management walk over and see your screen while its running, it tends
to look like you've automated something off your own bat to happen really
fast that you would otherwise be doing manually slowly.

Willy.


Brian Keating EI9FXB said:
Would I be correct in saying that the only way to get a user message into
a
Windows form would be to use P/Invoke with [Send/Post]Message?

Of is there some part of the .NET API that I am totally un aware of?

Thanks for any help
Brian
 
a) programs that constantly spool a load of text, fast, look *cool*.

This is true. However, you don't need to post hundreds of messages across
threads every second to make this happen.

In fact it's better if you don't.

You tend to get better results if you have as few transitions between the
worker thread and the UI thread as possible. If you throttle it to, say, 10
a second, and batch your updates, you can still scroll vast amounts of text
past the user, but you'll get your actual work done a lot faster.


--
Ian Griffiths - http://www.interact-sw.co.uk/iangblog/
DevelopMentor - http://www.develop.com/

Bonj said:
Now I still wonder why someone is placing all this stuff on the screen,
while I see hardly someone reading this at this speed.

I can think of several reasons:
a) programs that constantly spool a load of text, fast, look *cool*.
b) if it constantly spools a load of text there can be no doubt that it's
doing stuff.
c) you can read it faster if you know what it's likely to say. i.e, you
don't actually have to read it, so much as 'recognize' general textual
patterns.
d) if management walk over and see your screen while its running, it tends
to look like you've automated something off your own bat to happen really
fast that you would otherwise be doing manually slowly.

Willy.


Brian Keating EI9FXB said:
Would I be correct in saying that the only way to get a user message
into
a
Windows form would be to use P/Invoke with [Send/Post]Message?

Of is there some part of the .NET API that I am totally un aware of?

Thanks for any help
Brian
 
Back
Top