
Application Structure | 57
Forms, Apps,
Containers
This is the Title of the Book, eMatter Edition
Copyright © 2003 O’Reilly & Associates, Inc. All rights reserved.
and redraw requests. This means the framework needs to be in charge of our appli-
cation’s main thread most of the time; otherwise, it cannot deal with these events.
*
Although our application’s execution is stage-managed by the framework, we can
still influence its behavior by using the
Application class. For example, we can tell
the framework to shut down our program by calling the
Application.Exit
method. In fact, interacting with the Application class is the first thing most
programs do. They typically start like Example 3-1, calling
Application.Run to
surrender control to Windows Forms. This causes the framework to display the
Form object that it is given, after which it sits and waits for events. From then on,
our code will only be run as a result of some activity, such as a mouse click,
causing the framework to call one of our event handlers.
This event-driven style of execution is an important feature of Windows Forms.
The framework is able to deal with events only because we leave it in charge. Of
course, while one of our event handlers is running (e.g., the code in a
Click
handler is executing), we are temporarily back in charge, which means the frame-
work will be unable to process any other events until our event handler returns.
Most of the time, this is a good thing, because life would become unbearably
complex if we could be asked to start handling a new event before we had finished
dealing with the previous one; reentrant code is notoriously hard to get right, so it
is a good thing that it is not usually required.
The only problem is that if our event handlers take a long time to execute, the
user interface will become unresponsive. Until our code returns control to the
framework, the user will not be able to click on or type into our program, or to
move the windows around. (Strictly speaking the input won’t be lost—such
events are stored in a queue, just as they are with normal Windows programs. But
there will be no response to this input until the handler returns.) We can’t even
give the user a way to abort the operation if it takes too long because the inability
to process user input makes it difficult to support any kind of Cancel button.
While the obvious solution is to avoid writing event handlers that take too long to
execute, this is not always possible. Fortunately, long-running event handlers can
choose to give the framework a chance to deal with any events that may be
queued up and awaiting processing. The
Application class provides a method
called
DoEvents. This handles any pending input and then returns. Of course, any
code that calls this method needs to be careful, because it is inviting reentrant
behavior, so whenever you call this method, you must consider the implications
of another of your event handlers being run before
DoEvents returns. But it does
mean that slow code has a way of making sure the application does not appear to
lock up completely.
The DoEvents method is not the only way of reentering the framework’s event
handling code. Whenever you display a modal dialog (e.g., by using the
MessageBox class, or by displaying a form with the ShowDialog method, as
described later), Windows Forms is once again in charge of your thread and will
process events for you for as long as the window is displayed.
* This is similar to the way that classic Win32 applications must service the message queue.