6

I am designing a program that depends on monitoring the battery level of the computer.

This is the C# code I am using:

   PowerStatus pw = SystemInformation.PowerStatus;

   if (pw.BatteryLifeRemaining >= 75)
   {
       //Do stuff here
   }

My failed attempt of the while statement, it uses all the CPU which is undesirable.

    int i = 1;
    while (i == 1)
    {
        if (pw.BatteryLifeRemaining >= 75)
        {
           //Do stuff here
        }
    }

How do I monitor this constantly with an infinite loop so that when it reaches 75% it will execute some code.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Trontor
  • 417
  • 1
  • 7
  • 20
  • 1
    First: use `while(true)` instead of your while, second the `Do stuff here` stuff can break your code, while(true) won't (of course if you have `break` somewhere) :) – Kamil Budziewski Jul 24 '13 at 11:42
  • Move the monitor to a different thread. Forsee [a callback to the gui](http://msdn.microsoft.com/en-us/library/ms171728%28v=vs.80%29.aspx) to update your GUI – DarkBee Jul 24 '13 at 11:44
  • Wouldn't the While(true) create some unreachable code (as I have). @wud – Trontor Jul 24 '13 at 11:45
  • Therefor u should move it to another thread or use a backgroundworker (if u use WPF : [WPF dispatcher](http://tech.pro/tutorial/800/working-with-the-wpf-dispatcher)) – DarkBee Jul 24 '13 at 11:46
  • @Trontor if you have break statement it won't – Kamil Budziewski Jul 24 '13 at 11:47
  • @dark I don't understand what that means. I have only 3 months programming experience and would appreciate if you could explain in more noob-friendly detail – Trontor Jul 24 '13 at 11:48
  • Where could I place that @dark (is my @ tagging OTT or needed) – Trontor Jul 24 '13 at 11:48
  • @RowLandShaw Program becomes unresponsive but doesn't crash. Editing it – Trontor Jul 24 '13 at 11:49
  • 1
    In short, a thread is kind like a process. When u would use `while (true)` inside the default thread (The GUI thread), the GUI would become iresponsive. To prevent this from happening u need to create another thread (thread, backgroundworker, timer) to handle the while loop. The only problem is that only the GUI thread is able to update the GUI. Thats why u need to invoke the proper GUI thread and let it update its GUI... – DarkBee Jul 24 '13 at 11:54
  • You can try monitoring SystemInformation values with appropriate SystemEvents events – Dmitry Bychenko Jul 24 '13 at 12:07
  • I suggest you learn about threading - http://www.albahari.com/threading/ – dav_i Jul 24 '13 at 12:10
  • Which version of the .Net framework are you using? – Rowland Shaw Jul 24 '13 at 12:26
  • @RowlandShaw Version 4 – Trontor Jul 24 '13 at 12:28
  • 4
    If you make a tight loop that does nothing but check the battery level a thousand times a second then you'll very quickly converge on a battery level of zero. – Eric Lippert Jul 24 '13 at 14:53
  • Then is the chosen answer correct, or just power hungry? If so, what do you suggest? Timer? – Trontor Jul 24 '13 at 23:23
  • SystemEvents.PowerModeChanged as suggested by *A.Mokhtari* is the only way to go. – SeToY Jul 25 '13 at 20:22
  • I think the actual property that should be used is BatteryLifePercent. The BatteryLifeRemaining property returns the remaining running time in seconds, not in percentage. – Axonn May 02 '16 at 19:38
  • Use Windows Service to do such stuff , its not good to use infinite loops or timers. – N.K Sep 08 '17 at 03:20

3 Answers3

11

Try Timer:

public class Monitoring
{
    System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();

    public Monitoring()
    {
        timer1.Interval = 1000; //Period of Tick
        timer1.Tick += timer1_Tick;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        CheckBatteryStatus(); 
    }
    private void CheckBatteryStatus()
    {
        PowerStatus pw = SystemInformation.PowerStatus;

        if (pw.BatteryLifeRemaining >= 75)
        {
            //Do stuff here
        }
    }
}

UPDATE:

There is another way to do your task complete. You can use SystemEvents.PowerModeChanged. Call it and wait for changes, monitor the changes occured then do your stuff.

static void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e)
{
    if (e.Mode == Microsoft.Win32.PowerModes.StatusChange)
    {
         if (pw.BatteryLifeRemaining >= 75)
         {
          //Do stuff here
         }
    }
}
RSmeding
  • 3
  • 4
A.Mokhtari
  • 451
  • 5
  • 16
4

While loop will cause your UI to response poor and the application will get crashed. You can solve this by using many ways. Please check out the below code snippet will help your needs.

public delegate void DoAsync();

private void button1_Click(object sender, EventArgs e)
{
   DoAsync async = new DoAsync(GetBatteryDetails);
   async.BeginInvoke(null, null);
}

public void GetBatteryDetails()
{
   int i = 0;
   PowerStatus ps = SystemInformation.PowerStatus;
   while (true)
   {
     if (this.InvokeRequired)
         this.Invoke(new Action(() => this.Text = ps.BatteryLifePercent.ToString() + i.ToString()));
     else
         this.Text = ps.BatteryLifePercent.ToString() + i.ToString();

     i++;
   }
}
Vimal CK
  • 3,543
  • 1
  • 26
  • 47
2
BatteryChargeStatus.Text =  SystemInformation.PowerStatus.BatteryChargeStatus.ToString(); 
BatteryFullLifetime.Text  = SystemInformation.PowerStatus.BatteryFullLifetime.ToString();
BatteryLifePercent.Text  = SystemInformation.PowerStatus.BatteryLifePercent.ToString();
BatteryLifeRemaining.Text = SystemInformation.PowerStatus.BatteryLifeRemaining.ToString();
PowerLineStatus.Text = SystemInformation.PowerStatus.PowerLineStatus.ToString();

If you want to perform some operation just convert these string values into the integer.

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Monu Singh
  • 41
  • 3