Implement a SendMessage behaviour

F

Faust

Hi,

I'm trying to convert a Delphi application and I'm facing a case I
don't know how to solve.

Here is the problem: in Delphi, we've got an event fired when the
application becomes Idle (ie, when windows messages queue becomes
empty)

my application actually use this event to process "Next" action: on
user action the appplication push a new entry (or more) in a private
queue
and when then Idle event is fired, it look at the queue to know if
there's something to do
from an other point of view, it's the same behaviour than a SendMessage
(with a user defined message of course)

Do you know how I could implement the same (or similar) behaviour in C#
(3.5) ?

--
*/Teträm/*
http://www.tetram.org

"Mange d'abord, defeque ensuite: tu réfléchiras plus tard" - Proverbe
Troll
 
R

Rick Lones

Faust said:
Hi,

I'm trying to convert a Delphi application and I'm facing a case I don't
know how to solve.

Here is the problem: in Delphi, we've got an event fired when the
application becomes Idle (ie, when windows messages queue becomes empty)

my application actually use this event to process "Next" action: on user
action the appplication push a new entry (or more) in a private queue
and when then Idle event is fired, it look at the queue to know if
there's something to do
from an other point of view, it's the same behaviour than a SendMessage
(with a user defined message of course)

Do you know how I could implement the same (or similar) behaviour in C#
(3.5) ?

Hmm - for a quick hack - try running your queue consumer in a thread whose
priority is set one notch lower than the default. Seems like this would mimic
your behavior well enough for most purposes.

But, before even diddling with priorities I would check that running at the
default priority is not perfectly okay. Try the classic consumer thread that
blocks when the queue is empty before getting fancy.

hth,
-rick-
 
B

Ben Voigt [C++ MVP]

Faust said:
Hi,

I'm trying to convert a Delphi application and I'm facing a case I don't
know how to solve.

Here is the problem: in Delphi, we've got an event fired when the
application becomes Idle (ie, when windows messages queue becomes empty)

my application actually use this event to process "Next" action: on user
action the appplication push a new entry (or more) in a private queue
and when then Idle event is fired, it look at the queue to know if there's
something to do
from an other point of view, it's the same behaviour than a SendMessage
(with a user defined message of course)

Do you know how I could implement the same (or similar) behaviour in C#
(3.5) ?

SomeControl.BeginInvoke(SomeDelegate) would be equivalent to PostMessage,
not SendMessage, but I think it is the behavior you are looking for.

--
*/Teträm/*
http://www.tetram.org

"Mange d'abord, defeque ensuite: tu réfléchiras plus tard" - Proverbe
Troll



__________ Information from ESET NOD32 Antivirus, version of virus
signature database 4256 (20090718) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

__________ Information from ESET NOD32 Antivirus, version of virus signature database 4256 (20090718) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com
 
F

Faust

/_Ben Voigt [C++ MVP]_ a exposé/ :
SomeControl.BeginInvoke(SomeDelegate) would be equivalent to PostMessage, not
SendMessage, but I think it is the behavior you are looking for.

thanks for the tip
but I really need an empty call stack when the actions are started
(well, I needed that for a lot of reasons with Delphi; even if some are
no more a problem with .net, I guess some are still)
 
F

Faust

/Il se trouve que _Rick Lones_ a tapoté/ :
Hmm - for a quick hack - try running your queue consumer in a thread whose
priority is set one notch lower than the default. Seems like this would
mimic your behavior well enough for most purposes.
But, before even diddling with priorities I would check that running at the
default priority is not perfectly okay. Try the classic consumer thread that
blocks when the queue is empty before getting fancy.
hth,
-rick-

thanks for your answer
I think it will be very closer of what I want, but I don't really like
technics when there's a kind of "cross your finger" part (even just a
little). I prefer a solution that will work as expected in all cases.
I hope someone could have an other suggestion. Otherwise, I think I
will use this one.

--
*/Teträm/*
http://www.tetram.org

"C'est peut-être un détail pour vous, mais pour elles ça veut dire
beaucoup: les Trolles font pipi debout" - Simulmor le-Saxifrage Ainé
 
P

Peter Duniho

/_Ben Voigt [C++ MVP]_ a exposé/ :
[...]
SomeControl.BeginInvoke(SomeDelegate) would be equivalent to
PostMessage, not SendMessage, but I think it is the behavior you are
looking for.

thanks for the tip
but I really need an empty call stack when the actions are started
(well, I needed that for a lot of reasons with Delphi; even if some are
no more a problem with .net, I guess some are still)

Maybe you could describe your problem at a higher, more abstract level.

There's no such thing as "an empty call stack". By the time any of your
code gets to execute there is always at least a little bit of call stack,
and a GUI application is going to call as part of its first few actions a
..NET method that starts processing the window message queue (e.g.
Application.Run() for a Forms application), which will introduce even more
frames to the call stack.

The call stack also has very little to do with the message queue, and your
original post seemed to state you cared about the latter, not the former.

Also, your comments about SendMessage() are confusing, as SendMessage()
does not in any way guarantee that by the time the message sent is
actually processed that the window message queue is empty. In fact, a
message sent via SendMessage() doesn't go through the message queue at
all. If you call it from the thread that owns the window, it simply calls
the window class's window proc directly, and if from another thread the OS
simply ensures synchronization; it doesn't provide a guarantee that the
message queue is empty when the window class's window proc is actually
called.

Furthermore, there is no possible way to guarantee that the window message
queue is empty at the time that a particular message is handled, whether
that message was ever in the message queue or simply handled by a direct
call to the window proc. The instant that a particular thread might
_think_ that its message queue is empty, any code anywhere else could wind
up queuing a message to the queue, just as the particular thread was about
to start doing whatever "idle" processing is desired.

That's all a long way of saying that it is not literally possible to
accomplish what you seem to be saying you want to accomplish, and that
would be true for any Windows application.

Now, back to the basic things that _are_ possible:

-- In the unmanaged API there's SendMessage() and PostMessage().
SendMessage() being synchronous (doesn't return until the message is
processed) and PostMessage() being asynchronous (returns immediately, the
message to be processed later). In .NET, these are roughly equivalent to
Control.Invoke() and Control.BeginInvoke(), respectively. There are
obvious differences between the two paradigms, but in a very general sense
that would be the mapping.

-- In .NET, you can using the Application.Idle event
(http://msdn.microsoft.com/en-us/library/system.windows.forms.application.idle.aspx)
to detect when the message pump believes that the message queue is empty
and the application is about to enter an "idle" state. That event will
_not_ guarantee to you that there are in fact no messages in the queue
when your code executes, but then you never had that guarantee before. I
suspect that this event is the closest equivalent to what you were using
before, and would probably suffice for your purpose.

If the above doesn't help you, then you will probably have to provide a
more abstract, less implementation-specific description of what it is
you're really trying to accomplish. It's often difficult to provide good
advice when the question is presented as a specific implementation that
the questioner has already chosen, even if that implementation isn't
appropriate.

Pete
 
F

Faust

Thanks a lot, and yes, I made a big mistake

first, you're absolutly right, I made a big mistake between SendMessage
and PostMessage (my appologies to Ben too).

second, I know the call stack of a thread can't be empty but it was the
simpliest way I found to explain the feature I needed. I meant I need
as less as possible results of user actions in call stack of the thread
that will run the new action. The goal is really to simulate a
PostMessage: to wait all current actions (user click, timer event, etc)
are finished before starting the next one. As soon as the next action
is started, that's not a problem if the windows message queue receive
some message as they will wait my current action ends to be proceed
(unless I make some specific call in the new action to do it of course)

and third, the Idle event of Application seems to be exactly what i
need (more than BeginInvoke as, if I'm not worng, it build a thread to
run the delegate in the "same" time of the main thread)
I know it's not absolutly perfect because if my application is spammed
with some windows messages, there're some chances that the Idle event
never fire
but during the next 6 years, I'd never saw that case :)

thx again :)

/Après mure réflexion, _Peter Duniho_ a écrit/ :
[...]
SomeControl.BeginInvoke(SomeDelegate) would be equivalent to PostMessage,
not SendMessage, but I think it is the behavior you are looking for.

thanks for the tip
but I really need an empty call stack when the actions are started (well, I
needed that for a lot of reasons with Delphi; even if some are no more a
problem with .net, I guess some are still)
[/QUOTE]
Maybe you could describe your problem at a higher, more abstract level.
There's no such thing as "an empty call stack". By the time any of your code
gets to execute there is always at least a little bit of call stack, and a
GUI application is going to call as part of its first few actions a .NET
method that starts processing the window message queue (e.g.
Application.Run() for a Forms application), which will introduce even more
frames to the call stack.
The call stack also has very little to do with the message queue, and your
original post seemed to state you cared about the latter, not the former.
Also, your comments about SendMessage() are confusing, as SendMessage() does
not in any way guarantee that by the time the message sent is actually
processed that the window message queue is empty. In fact, a message sent
via SendMessage() doesn't go through the message queue at all. If you call
it from the thread that owns the window, it simply calls the window class's
window proc directly, and if from another thread the OS simply ensures
synchronization; it doesn't provide a guarantee that the message queue is
empty when the window class's window proc is actually called.
Furthermore, there is no possible way to guarantee that the window message
queue is empty at the time that a particular message is handled, whether that
message was ever in the message queue or simply handled by a direct call to
the window proc. The instant that a particular thread might _think_ that its
message queue is empty, any code anywhere else could wind up queuing a
message to the queue, just as the particular thread was about to start doing
whatever "idle" processing is desired.
That's all a long way of saying that it is not literally possible to
accomplish what you seem to be saying you want to accomplish, and that would
be true for any Windows application.
Now, back to the basic things that _are_ possible:
-- In the unmanaged API there's SendMessage() and PostMessage().
SendMessage() being synchronous (doesn't return until the message is
processed) and PostMessage() being asynchronous (returns immediately, the
message to be processed later). In .NET, these are roughly equivalent to
Control.Invoke() and Control.BeginInvoke(), respectively. There are obvious
differences between the two paradigms, but in a very general sense that would
be the mapping.
-- In .NET, you can using the Application.Idle event
(http://msdn.microsoft.com/en-us/library/system.windows.forms.application.idle.aspx)
to detect when the message pump believes that the message queue is empty and
the application is about to enter an "idle" state. That event will _not_
guarantee to you that there are in fact no messages in the queue when your
code executes, but then you never had that guarantee before. I suspect that
this event is the closest equivalent to what you were using before, and would
probably suffice for your purpose.
If the above doesn't help you, then you will probably have to provide a more
abstract, less implementation-specific description of what it is you're
really trying to accomplish. It's often difficult to provide good advice
when the question is presented as a specific implementation that the
questioner has already chosen, even if that implementation isn't appropriate.

--
*/Teträm/*
http://www.tetram.org

"Ecoute toujours ton estomac, c'est quelqu'un de confiance" - Proverbe
Troll
 
P

Peter Duniho

[...]
and third, the Idle event of Application seems to be exactly what i need
(more than BeginInvoke as, if I'm not worng, it build a thread to run
the delegate in the "same" time of the main thread)

Just to clarify: there are (at least) two BeginInvoke() methods in .NET.
Control.BeginInvoke() and Delegate.BeginInvoke() (or rather, the
auto-generated BeginInvoke() created for each delegate type). The former
is what we're discussing here and it doesn't create a new thread; the
latter is what causes a delegate method to be invoked on the thread pool
(which may or may not cause a new thread to be created).

Anyway, sounds like you should try Application.Idle. If that works, then
you're done. :)

Pete
 
F

Faust

/_Peter Duniho_ a exposé/ :
[...]
and third, the Idle event of Application seems to be exactly what i need
(more than BeginInvoke as, if I'm not worng, it build a thread to run the
delegate in the "same" time of the main thread)
Just to clarify: there are (at least) two BeginInvoke() methods in .NET.
Control.BeginInvoke() and Delegate.BeginInvoke() (or rather, the
auto-generated BeginInvoke() created for each delegate type). The former is
what we're discussing here and it doesn't create a new thread; the latter is
what causes a delegate method to be invoked on the thread pool (which may or
may not cause a new thread to be created).
Anyway, sounds like you should try Application.Idle. If that works, then
you're done. :)

after, test it's exactly what I need
thx all.

--
*/Teträm/*
http://www.tetram.org

"Le monde est rond comme le cul d'une pucelle. On ne peut pas s'y
perdre"
Chevalier Or-Azur
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top