Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / C#

Writing a Correct Main Loop for Your Application

Rate me:
Please Sign up or sign in to vote.
4.60/5 (3 votes)
30 Dec 2009CPOL4 min read 19.1K   5   1
How to write a correct main loop for your application

Have you ever wondered how Windows can run more than one application at a time, even in a single-processor machine? The answer is easy. It doesn’t. The point is that it switches from one application to another so fast that you don´t notice the change, and it seems both applications are running in parallel.

To allow this, running Windows applications should not always be running.

It´d be a waste of resources to massively use the processor just to find out that nothing had to be done, don’t you think? That´d be kind of a psychotic behavior. Windows has its protocols and procedures to avoid this, letting applications or threads enter idle states, even for a few milliseconds, and giving then priority to other, non-idling processes.

So, what would happen if your application never enters idle mode? It would bring down the multi-tasking capability of Windows, slowing down every other application than yours. That´s why I say that running applications should not always be running.

Under this point of view, applications can be divided into three groups:

  1. Psychotic applications that should be updated always, i.e., intense computing applications (not so frequent, nowadays)
  2. Applications that should be updated only as a response to some user interaction (most Windows Forms applications)
  3. Applications that sometimes need to be “always updated”, and sometimes not (like a video-game)

As you know, when an application is run, the Main method is invoked, and the O.S. gives the application access to the processor and some memory. Apart from thread priority policies, application´s behavior will be one or another depending on what we do in this Main() method:

Case # 1. Compute, Compute, Compute

The Main method structure is simple: update as fast as you can, and consume as much processor as possible. The Main() method in pseudo-code:

C#
while (Application is Alive)
{
    Compute()
}

This is the typical behavior of old applications in non multi-tasking environments. They consume as much processing power as is available.

Case # 2. Don´t Disturb Unless Absolutely Necessary

What should be done here is easy: if events are pending, process them (DoEvents). If not, just relax and sleep, yielding processor to other threads or applications. The exact implementation of such a procedure can be more complex, as we should decide when to enter sleep modes and when not. Luckily, .NET does that for us. The C# implementation you should use is:

C#
System.Windows.Forms.Application.Run(mForm);

The Run() method takes care of all the things above mentioned (yielding and many other things), and it does it using the standard .NET procedures and protocols.

Case # 3: The Mixed Approach

Other situations need a mixed solution. For example, a Windows Forms application that sometimes needs to enter a “running” state, where everything has to be updated, like a Windows Forms-based video-game, or a 3D editor where you want to run an animation. Here, updates will be applied when the application is in Running state, but not when it´s not, saving this way CPU (and batteries, if running in a laptop).

So, we want to combine the efficiency of Case # 2, with the possibility of switching to Case # 1 when needed. The correct implementation for this, in C#, is:

C#
...
     System.Windows.Forms.Application.Idle += new EventHandler(Application_Idle);
     System.Windows.Forms.Application.Run(mForm);
 }
 static void Application_Idle(object sender, EventArgs e)
 {
     if(Application.RunningState)
          Compute();
 }

The Application_Idle event will be fired each time the application is about to enter in Idle state (where all the pending messages for the windows has been processed). There we can decide to leave it sleep, or to update computations, depending on application´s “Running” state.

This way, interaction between our application and others (running at the same time) will be correct: when we decide it (activate running state), we will have all the computing power for ourselves, but when it´s not needed (RunningState is off), we will yield it.

An Extra Option to Make Things Even Better

We have seen how to activate/deactivate the psychotic (processor consuming) behavior of an application, basing on a state variable, but sometimes it is interesting to also deactivate it when our application does not have the focus (it is not the active application in the O.S.).

Windows controls and forms have a “Focused” property, but that doesn’t help much in this case, as we want to check if the entire application has focus, not an specific form (the main form of the application will lose focus often, when we open a child window, for instance).

Then, how to check if our application is the active application in Windows? Unfortunately, it seems that there is no C# managed code to check that, but we can easily use DLLImport to invoke the “GetForegroundWindow” method, comparing its result to our main form handle:

C#
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
 
public bool MyAppFocused
{
    get { return GetForegroundWindow() == this.Handle; }
}

This way, we can put an additional condition to the Compute method, deactivating it also when the application is not focused:

C#
static void Application_Idle(object sender, EventArgs e) 
{ 
   if(Application.RunningState && MyAppFocused) 
       Compute(); 
}

What Should Not Be Done

Some people tend to write the following code when they need the mixed solution mentioned:

C#
while (mForm.Created)
{
      System.Windows.Forms.Application.DoEvents();

      if(Application.RunningState) 
             Compute();
}

Though it works, this approach is not correct, as it doesn’t yield processor to other threads (your application won´t enter idle mode). Use the above Idle event approach instead.

Conclusion

Quality software use the processor when they really need it. Adding a few extra lines of code, you software will better share resources with other applications, and will improve laptop or handheld device´s battery life.

Take care!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Spain Spain
Inaki Ayucar is a Microsoft MVP in DirectX/XNA, and a software engineer involved in development since his first Spectrum 48k, in the year 1987. He is the founder and chief developer of The Simax Project (www.simaxvirt.com) and is very interested in DirectX/XNA, physics, game development, simulation, C++ and C#.

His blog is: http://graphicdna.blogspot.com

To contact Inaki: iayucar@simax.es

Comments and Discussions

 
GeneralMy vote of 5 Pin
JH6424-May-12 19:01
JH6424-May-12 19:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.