Application.Run()

  • Thread starter Thread starter Uchiha Jax
  • Start date Start date
U

Uchiha Jax

Hi,

Recently had an issue with the Audio object from
Microsoft.DirectX.AudioVideoPlayback. None of the events were firing from
the object during tests (NUnit or Console). Knowing I had it working
perfectly well in the application running on my tablet PC next to me, I
managed to narrow down the defining factor between the two applications and
found that it was a one line difference.

Application.Run().

I found I could "fix" my test by putting Application.Run at the end of the
thread that initializes the object. This is of course equivalent to loading
it into a Form and running the same thread in the LoadEvent of the form.
Having never encountered this problem before I had some questions that I
wondered if anyone could help me understand.

What exactly is the "standard application message loop" (from MS
documentation:
http://msdn.microsoft.com/library/d...ystemWindowsFormsApplicationClassRunTopic.asp)
and how does this differ to a standard thread event model?
Are there ways in which you can find out if an object requires the "standard
application message loop" other than trial and error?
Does anyone have any other information on this subject as I find it a
fascinating situation.

If anyone could drop some knowledge i'd appreciate it as I don't understand
this at all.

Kind Regards

Jax
 
Uchiha said:
What exactly is the "standard application message loop" (from MS
documentation:
http://msdn.microsoft.com/library/d...ystemWindowsFormsApplicationClassRunTopic.asp)
and how does this differ to a standard thread event model?
Are there ways in which you can find out if an object requires the
"standard application message loop" other than trial and error?
Does anyone have any other information on this subject as I find it a
fascinating situation.

new Form();

just creates a form object, it does not create the form window

Form f = new Form();
f.Visible = true;

the second line will create the window. In this property accessor a
Win32 window class is registered, then a window is created. Every window
has to have a windows procedure that handles messages. The messages are
put into a queue for the thread and a loop on the thread calls
GetMessage() to get a message from this queue and then passes it to the
windows procedure by calling DispatchMessage().

There is another aspect that you should be aware of. If a thread
procedure returns, the thread dies. So if your application has just one
thread, your application will live as long as the thread lives. (This
assumes that the thread is a foreground thread.) Even if the application
has a window and you have *not* clicked on the close button, if the
thread procedure finishes then the application will die. Try this:

class App
{
static void Main()
{
Form f = new Form();
f.Visible = true;
}
}

What happens? The form shows briefly and then goes away. The reason is
that the window is created but the thread procedure completes so the
process dies and the window is destroyed. Also, this window will not
respond to windows messages. to get round this you can add a call to
Application.Run() after the call to set the Visible property.

Now the window will remain, because Run implements a
GetMessage/DispatchMessage loop, so the main thread does not die. The
loop also means that the form will handle messages sent by the OS.
However there is a problem. If you click on the close button of the
form, the window will go away, but if you run task manager you'll see
that the process is still running. The problem is that the Visible set
accessor provides a windows procedure that handles the click on the
close button to close the window, but this windows procedure has no
connection to the application - it cannot tell the application to end.
This needs something called an application context, which is a
connection between the window and the message queue. If you pass the
form object to Application.Run an application context will be created. I
won't go into the details, but basically the application context is
based on the form, and if the form dies the application context breaks
the message loop and so the process dies. If the message queue dies then
the application context tells the form object (as opposed to the window)
to allow your code to clean up (Dispose is called).

Thus the life of the process is determined by the life of the form. Any
other form in the application will not have the application context and
so will not kill the process when it is closed.
I found I could "fix" my test by putting Application.Run at the end
of the thread that initializes the object. This is of course
equivalent to loading it into a Form and running the same thread in
the LoadEvent of the form. Having never encountered this problem
before I had some questions that I wondered if anyone could help me
understand.

Hopefully the above will explain what's going on.

I wrote an article for DDJ about this, but unfortunately you have to
register to read it:

http://www.ddj.com/documents/s=9698/ddj0505l/0505l.html

I am considering writing a workshop on how windows forms work (on the
lines of my workshops on Fusion and on Security), but to be honest at
the moment I'm quite pissed off with Microsoft so I don't seem to have
any incentive to do so.

Richard
 
That's excellent, thanks for the information!
I appreciate that you have trawled back through the posts to answer this
question that was left unanswered so long ago.

Many, many thanks.

UchihaJax (Simon)
 
Back
Top