This is a multi-part message in MIME format.

------=_NextPart_000_0009_01C5B066.058A4E30
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

We have an application written in c# that uses pinvoke to call =
SendMessage to send messages between threads. We also use Monitor class =
(via the c# lock keyword) for thread synchronization.=20

I have discovered the following behaviour, which surprised me:

0) Thread1 (T1) creates a NativeWindow, to be used as a SendMessage =
target, then calls Application.Run()
1) T1 enters an event handler
2) inside the event handler, T1 enters a lock region (calls =
Monitor.Enter), but blocks because another thread (call it T2) has =
entered
3) T3 calls SendMessage on the NativeWindow created by T1
4) The message handler for the message sent in 3) is run, while T1 is in =
the Monitor.Enter() call.

If I do the following experiment, I get different behaviour (code =
changes in bold)

0) Thread1 (T1) creates a System.Windows.Forms.Control, to be used as an =
Invoke target, then calls Application.Run()
1) T1 enters an event handler
2) inside the event handler, T1 enters a lock region (calls =
Monitor.Enter), but blocks because another thread (call it T2) has =
entered
3) T3 calls Invoke on the Control created by T1
4) T1 Monitor.Enter() returns (T2 called Monitor.Exit), and ultimately =
the event handler T1 is running returns
5) The delegate passed into Control.Invoke() in step 3) runs

The behaviour in the 2nd experiment is what I was expecting in the first =
experiments' case. It appears, in the first experiments case, that =
inside Monitor.Enter(), messages sent by SendMessage are being =
dispatched before it returns.

Does anyone have any idea what I can do, in the SendMessage case, to get =
the behaviour I am seeing using Control.Invoke()? I would rather not use =
Control.Invoke() because it has a couple limitations relative to using =
SendMessage() (but I may have to...)

Thanks for any insights any of you might have.

Craig Bryant
Senior Software Engineer
Tektronix, Inc
Beaverton, OR
------=_NextPart_000_0009_01C5B066.058A4E30
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2900.2627" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY>
<DIV><FONT face=3DArial size=3D2>We have an application written in c# =
that uses=20
pinvoke to call SendMessage to send messages between threads. We also =
use=20
Monitor class (via the c# lock keyword) for thread=20
synchronization.&nbsp;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>I have discovered the following =
behaviour, which=20
surprised me:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>0) Thread1 (T1) creates a NativeWindow, =
to be used=20
as a SendMessage target, then calls Application.Run()</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>1) T1&nbsp;enters an event =
handler</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>2) inside the event handler, T1 enters =
a lock=20
region (calls Monitor.Enter), but blocks&nbsp;because another thread =
(call it=20
T2) has entered</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>3) T3 calls SendMessage on&nbsp;the =
NativeWindow=20
created by T1</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>4) The message handler for the message =
sent in 3)=20
is run, <EM>while T1 is in the Monitor.Enter() call</EM>.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>If I do the following experiment, I get =
different=20
behaviour (code&nbsp;changes in bold)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>0) Thread1 (T1) creates a=20
<STRONG>System.Windows.Forms.Control</STRONG>, to be used as an Invoke =
target,=20
then calls Application.Run()</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>1) T1&nbsp;enters an event =
handler</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>2) inside the event handler, T1 enters =
a lock=20
region (calls Monitor.Enter), but blocks&nbsp;because another thread =
(call it=20
T2) has entered</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>3) T3 calls <STRONG>Invoke on the =
Control</STRONG>=20
created by T1</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>4) T1 Monitor.Enter() returns (T2 =
called=20
Monitor.Exit), and ultimately the event handler T1 is running=20
returns</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>5) The delegate passed into =
Control.Invoke() in=20
step 3) runs</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>The behaviour in the 2nd experiment is =
what I was=20
expecting in the first experiments' case. It appears, in the first =
experiments=20
case, that inside Monitor.Enter(), messages sent by SendMessage are =
being=20
dispatched before it returns.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>Does anyone have any idea what I can =
do, in the=20
SendMessage case, to get the behaviour I am seeing using =
Control.Invoke()? I=20
would rather not use Control.Invoke() because it has a couple =
limitations=20
relative to using SendMessage() (but I may have to...)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>Thanks for any insights any of you =
might=20
have.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>Craig Bryant</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Senior Software Engineer</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Tektronix, Inc</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Beaverton, =
OR</FONT></DIV></BODY></HTML>

------=_NextPart_000_0009_01C5B066.058A4E30--

Re: System.Threading.Monitor and SendMessage by Cool

Cool
Sun Sep 04 23:56:04 CDT 2005

Craig Bryant <dont@spam.me.com> wrote:

> Does anyone have any idea what I can do, in the SendMessage case, to get the behaviour I am seeing using Control.Invoke()? I would rather not use Control.Invoke() because it has a couple limitations relative to using SendMessage() (but I may have to...)

It might be rewarding to look at the code for Control.Invoke in Reflector.

Re: System.Threading.Monitor and SendMessage by Craig

Craig
Mon Sep 05 22:25:07 CDT 2005

Thanks for the response - sounds like a good idea. But I am not familiar
with the Reflector you mention. Could you provide a link? (Are you thinking
of Rotor?)

"Cool Guy" <coolguy@abc.xyz> wrote in message
news:1gakpgp121338$.dlg@cool.guy.abc.xyz...
> Craig Bryant <dont@spam.me.com> wrote:
>
>> Does anyone have any idea what I can do, in the SendMessage case, to get
>> the behaviour I am seeing using Control.Invoke()? I would rather not use
>> Control.Invoke() because it has a couple limitations relative to using
>> SendMessage() (but I may have to...)
>
> It might be rewarding to look at the code for Control.Invoke in Reflector.



Re: System.Threading.Monitor and SendMessage by Cool

Cool
Tue Sep 06 00:16:52 CDT 2005

Craig Bryant <dont@spam.me.com> wrote:

> Thanks for the response - sounds like a good idea. But I am not familiar
> with the Reflector you mention. Could you provide a link? (Are you thinking
> of Rotor?)

No, this: <http://www.aisto.com/roeder/dotnet/>.

With it you can view C# code, for example, representing compiled MSIL. So
you could use it to view the innards of Control.Invoke.

Re: System.Threading.Monitor and SendMessage by Craig

Craig
Tue Sep 06 10:00:45 CDT 2005

Thanks for the info.

"Cool Guy" <coolguy@abc.xyz> wrote in message
news:2ozacz49te5g$.dlg@cool.guy.abc.xyz...
> Craig Bryant <dont@spam.me.com> wrote:
>
>> Thanks for the response - sounds like a good idea. But I am not familiar
>> with the Reflector you mention. Could you provide a link? (Are you
>> thinking
>> of Rotor?)
>
> No, this: <http://www.aisto.com/roeder/dotnet/>.
>
> With it you can view C# code, for example, representing compiled MSIL. So
> you could use it to view the innards of Control.Invoke.



Re: System.Threading.Monitor and SendMessage by Nigel

Nigel
Fri Oct 07 12:59:22 CDT 2005

Craig,

Try reading this article:

http://blogs.msdn.com/cbrumme/archive/2004/02/02/66219.aspx

Set yourself up with a strong cup of coffee and plenty of time before
starting.

Basically when your STA thread is 'blocked' on the Monitor.Enter, it's
not actually idle - it's busy pumping windows messages. Hence in your
first test, your windows message can be processed even though the thread
is supposedly waiting on the Monitor.

Quite why Invoke behaves differently I haven't tried to figure out.

-----
Nigel Norris

"Craig Bryant" <dont@spam.me.com> wrote in message
news:eVgAzCKsFHA.2948@TK2MSFTNGP15.phx.gbl...
We have an application written in c# that uses pinvoke to call
SendMessage to send messages between threads. We also use Monitor class
(via the c# lock keyword) for thread synchronization.

I have discovered the following behaviour, which surprised me:

0) Thread1 (T1) creates a NativeWindow, to be used as a SendMessage
target, then calls Application.Run()
1) T1 enters an event handler
2) inside the event handler, T1 enters a lock region (calls
Monitor.Enter), but blocks because another thread (call it T2) has
entered
3) T3 calls SendMessage on the NativeWindow created by T1
4) The message handler for the message sent in 3) is run, while T1 is in
the Monitor.Enter() call.

If I do the following experiment, I get different behaviour (code
changes in bold)

0) Thread1 (T1) creates a System.Windows.Forms.Control, to be used as an
Invoke target, then calls Application.Run()
1) T1 enters an event handler
2) inside the event handler, T1 enters a lock region (calls
Monitor.Enter), but blocks because another thread (call it T2) has
entered
3) T3 calls Invoke on the Control created by T1
4) T1 Monitor.Enter() returns (T2 called Monitor.Exit), and ultimately
the event handler T1 is running returns
5) The delegate passed into Control.Invoke() in step 3) runs

The behaviour in the 2nd experiment is what I was expecting in the first
experiments' case. It appears, in the first experiments case, that
inside Monitor.Enter(), messages sent by SendMessage are being
dispatched before it returns.

Does anyone have any idea what I can do, in the SendMessage case, to get
the behaviour I am seeing using Control.Invoke()? I would rather not use
Control.Invoke() because it has a couple limitations relative to using
SendMessage() (but I may have to...)

Thanks for any insights any of you might have.

Craig Bryant
Senior Software Engineer
Tektronix, Inc
Beaverton, OR