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 it´s 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:
- Psychotic applications that should be updated always, i.e. intense computing applications (not so frequent, nowadays)
- Applications that should be updated only as a response to some user interaction (most Windows Forms applications)
- Applications that sometimes need to be “always updated”, and sometimes not (like a video-game)
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:
while (Application is Alive)
{
Compute()
}
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:
System.Windows.Forms.Application.Run(mForm);
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:
...
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)
{
while(ApplicationStillIdle)
Compute();
}
}
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.
How to check if application is still Idle
The Application_Idle event is fired only once, when the application is about to enter idle state. Here, we will have to update computations while it is still Idle, giving priority to Windows Messages if there are some. How to check if the application is still Idle? Easy, we can use a property like the following:
/// <summary>Checks to see if the application is still idle</summary>
private bool AppStillIdle
{
get
{
NativeMethods.Message msg;
return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
}
}
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 loose 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:
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
public bool MyAppFocused
{
get { return GetForegroundWindow() == this.Handle; }
}
static void Application_Idle(object sender, EventArgs e){if(Application.RunningState && MyAppFocused){while(ApplicationStillIdle)Compute();}
}
What should not be done
Some people tend to write the following code when need the mixed solution mentioned:
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 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!