C#, Constantly monitor battery level
Asked Answered
G

3

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.

Glucinum answered 24/7, 2013 at 11:40 Comment(18)
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) :)Field
Move the monitor to a different thread. Forsee a callback to the gui to update your GUITadeo
Wouldn't the While(true) create some unreachable code (as I have). @wudGlucinum
Therefor u should move it to another thread or use a backgroundworker (if u use WPF : WPF dispatcher)Tadeo
@Glucinum if you have break statement it won'tField
@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 detailGlucinum
Where could I place that @dark (is my @ tagging OTT or needed)Glucinum
@RowLandShaw Program becomes unresponsive but doesn't crash. Editing itGlucinum
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...Tadeo
You can try monitoring SystemInformation values with appropriate SystemEvents eventsShiest
I suggest you learn about threading - albahari.com/threadingDefloration
Which version of the .Net framework are you using?Yonah
@RowlandShaw Version 4Glucinum
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.Gorrian
Then is the chosen answer correct, or just power hungry? If so, what do you suggest? Timer?Glucinum
SystemEvents.PowerModeChanged as suggested by A.Mokhtari is the only way to go.Speciation
I think the actual property that should be used is BatteryLifePercent. The BatteryLifeRemaining property returns the remaining running time in seconds, not in percentage.Giuliana
Use Windows Service to do such stuff , its not good to use infinite loops or timers.Goad
P
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
         }
    }
}
Polik answered 24/7, 2013 at 11:46 Comment(2)
Definitely go with the "update" method. Constantly polling is a horrible way to check battery life. It sort of defeats the whole purpose. If it were me, I'd just remove the first part of the answer altogether.Nesto
what is pw here ?Goad
S
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++;
   }
}
Scheller answered 24/7, 2013 at 12:13 Comment(0)
F
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.

Fry answered 25/7, 2015 at 20:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.