Message Loops and Application.Run()

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

Guest

My code creates a new thread and in that thread I
call System.Windows.Forms.Application.Run() to start
an application message loop. ( I also have a message
filter added on that thread to handle incoming messages.)

Now, how do I actually send messages to the
message loop since there's no window defined on that thread?
There must be a way since the MSDN doc for Application.Run()
states: "Begins running a standard application message loop on the current
thread, without a form." I looked at the System.Messaging namespace
but I'm not even sure if MSMQ is the same thing as an Application
Message loop.

Any help appreciated.
Thanks!
Steve
 
Now, how do I actually send messages to the
message loop since there's no window defined on that thread?
There must be a way since the MSDN doc for Application.Run()
states: "Begins running a standard application message loop on the current
thread, without a form." I looked at the System.Messaging namespace
but I'm not even sure if MSMQ is the same thing as an Application
Message loop.

what kind of messages would you like to send to the message loop without a
window?

[btw. msmq is not the same thing as appliaction message loop]

Wiktor Zychla
 
Wiktor Zychla said:
Now, how do I actually send messages to the
message loop since there's no window defined on that thread?
There must be a way since the MSDN doc for Application.Run()
states: "Begins running a standard application message loop on the current
thread, without a form." I looked at the System.Messaging namespace
but I'm not even sure if MSMQ is the same thing as an Application
Message loop.

what kind of messages would you like to send to the message loop without a
window?

[btw. msmq is not the same thing as appliaction message loop]

Wiktor Zychla

Well, I'm calling a vendor API that requires calls to be made on a thread
with a message loop. But the DLL I'm writing is being called from an
application that spawns a new thread w/o a message loop. So, right now, I'm
creating a hidden window and then calling Application.Run(HiddenForm) in a
new thread. Then whenever my parent application calls my DLL, I can use
HiddenForm.Invoke to run the vendor function which guarentees it will be
running in a thread that has a message loop.

Having a form (hidden or not) doesn't seem like the most efficient or
elegant solution. I was hoping to (1) Create a new thread, (2)define a
message handler using Application.AddMessageFilter, (3) call
Application.Run() on the new thread which creates an Application message
loop, and finally (4) Put messages on that loop which basically equates to
"call function X" or "call function Y".... same thing as using
Control.Invoke() only without the hidden form.

Do I have to use a Win32 API call to send a message? Is that possible
without a Window handle?
Is there any better doc out there for Windows messaging?
I couldn't find anything on MSDN.

Thanks!!!
Steve
 
Is that possible without a Window handle?

Yes, with the PostThreadMessage function. I'm not sure whether such
messages are routed via IMessageFilters though.



Mattias
 
Well, I'm calling a vendor API that requires calls to be made on a thread
with a message loop. But the DLL I'm writing is being called from an
application that spawns a new thread w/o a message loop. So, right now,
I'm
creating a hidden window and then calling Application.Run(HiddenForm) in a
new thread. Then whenever my parent application calls my DLL, I can use
HiddenForm.Invoke to run the vendor function which guarentees it will be
running in a thread that has a message loop.

Having a form (hidden or not) doesn't seem like the most efficient or
elegant solution. I was hoping to (1) Create a new thread, (2)define a
message handler using Application.AddMessageFilter, (3) call
Application.Run() on the new thread which creates an Application message
loop, and finally (4) Put messages on that loop which basically equates to
"call function X" or "call function Y".... same thing as using
Control.Invoke() only without the hidden form.

Do I have to use a Win32 API call to send a message? Is that possible
without a Window handle?
Is there any better doc out there for Windows messaging?
I couldn't find anything on MSDN.

win32 messages are rather designed to support operations on interface
windows. that's why I am a little surprized that you need a message loop
without any window. the message loop in win32 looks basically like this

while ( GetMessage( ... ) ) {
DispatchMessage( ... );
}

having no window you can even forget the DispatchMessage function because it
directs the message to a proper window procedure.

I think then that you should try to bite the problem from the other side. do
not use Application.Run() and do not use Application.AddMessageFilter.
instead you could try to p/invoke the win32 GetMessage(...) function and get
the same result. after getting the message you could see if the message code
suits you.

to send the message you need to p/invoke win32 SendMessage(). you can use
HWND_BROADCAST (0xffff) to broadcast the message, however, I do not know if
it will reach a thread that did not create any window.

I am still a little confused of what you are trying to do. do you actually
need to create a message loop, put messages to existing message loop or
both?

Wiktor
 
Wiktor,
I think the information you and Mattias has given me is sufficient to solve
my problem. To answer your question about "why?".... unfortunately my code
is sandwiched between a desktop app and a vendor's SDK. The vendor is the one
that requires a message loop, and I also want all my vendor calls to happen
on the same thread.

I greatly appreciate your help.
Steve
 
Steve said:
Wiktor Zychla said:
Now, how do I actually send messages to the
message loop since there's no window defined on that thread?
There must be a way since the MSDN doc for Application.Run()
states: "Begins running a standard application message loop on the current
thread, without a form." I looked at the System.Messaging namespace
but I'm not even sure if MSMQ is the same thing as an Application
Message loop.

what kind of messages would you like to send to the message loop without a
window?

[btw. msmq is not the same thing as appliaction message loop]

Wiktor Zychla

Well, I'm calling a vendor API that requires calls to be made on a thread
with a message loop. But the DLL I'm writing is being called from an
application that spawns a new thread w/o a message loop. So, right now, I'm
creating a hidden window and then calling Application.Run(HiddenForm) in a
new thread. Then whenever my parent application calls my DLL, I can use
HiddenForm.Invoke to run the vendor function which guarentees it will be
running in a thread that has a message loop.

Having a form (hidden or not) doesn't seem like the most efficient or
elegant solution. I was hoping to (1) Create a new thread, (2)define a
message handler using Application.AddMessageFilter, (3) call
Application.Run() on the new thread which creates an Application message
loop, and finally (4) Put messages on that loop which basically equates to
"call function X" or "call function Y".... same thing as using
Control.Invoke() only without the hidden form.

Do I have to use a Win32 API call to send a message? Is that possible
without a Window handle?
Is there any better doc out there for Windows messaging?
I couldn't find anything on MSDN.

Thanks!!!
Steve
I'm not sure if using the message pump to pass data to your thread is the
best way. I guess it depends on how the callbacks are initiated from the
vendor API. I have a similar situation where the vendor API is a COM server
component that does callbacks via Connection Point events. What I did was:

1) Created a class that inherits from System.Windows.Forms.Control. This
will allow you to create a control with a window handle, which is required
in order to have a Message Pump.
2) Create a thread from your main GUI thread. In the startup method of the
thread, instantiate the control. Then, create the window handle for the
control using the CreateControl method.
3) Call Application.Run() in the startup method of step #2. This will keep
the spawned thread alive. The control can now be used to accept Connection
Point callbacks from COM objects created and owned by the user control.

It is important that any calls from the main GUI thread to the user control
and vice-versa be wrapped in Invoke or BeginInvoke statements. This will
prevent certain odd multi-threading issues. What I did was pass a reference
of the owner control to the created user control, and then use the owner
control reference to issue Invoke callbacks. You need to be careful about
simply using Invoke instead of BeginInvoke, as it opens you up to potential
thread Deadlock issues. For example, if your main GUI thread uses Invoke to
call into your User control, and then your user control calls Invoke to
return an Exception to your main GUI thread, a thread deadlock will occur.
There is no simple answer for when it is best to use Invoke vs.
BeginInvoke...it depends on your application requirements.

Regards,
MP
 
Back
Top