C# .NET桌面开发中如何实现PC电池百分比变动时触发事件
实现方案
Windows系统本身未公开专门针对电池百分比变动的系统级事件,以下是两种稳定可行的实现方式:
方案1:轻量定时器轮询(推荐,实现最简单、稳定性最高)
该方案是业内通用的实现方式,低频率轮询对系统资源的消耗可以忽略,完全满足实时更新的需求:
实现步骤
- 把电池信息更新逻辑抽离为公共方法,增加变化校验避免无效UI重绘
// 缓存上一次的电量值,避免重复更新界面 private string _lastBatteryValue = string.Empty; private void UpdateBatteryInfo() { PowerStatus power = SystemInformation.PowerStatus; string currentValue; if (power.PowerLineStatus == PowerLineStatus.Online) { currentValue = "P"; } else if (power.PowerLineStatus == PowerLineStatus.Offline) { // 四舍五入取整,避免展示小数 currentValue = $"{Math.Round(power.BatteryLifePercent * 100, 0)} %"; } else { currentValue = "未知"; } // 仅当数值发生变化时才更新UI,减少不必要的渲染消耗 if (currentValue != _lastBatteryValue) { BatteryPercentage = currentValue; _lastBatteryValue = currentValue; } }
- 初始化UI线程定时器,定时触发更新(WinForms示例,WPF可改用DispatcherTimer)
private System.Windows.Forms.Timer _batteryMonitorTimer; private void Form_Load(object sender, EventArgs e) { // 绑定原有电源模式变更事件,处理插拔电的即时响应 SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; // 配置定时器,间隔可按需调整,1-10秒都属于合理范围,不会增加额外耗电 _batteryMonitorTimer = new System.Windows.Forms.Timer { Interval = 3000 // 3秒更新一次 }; _batteryMonitorTimer.Tick += (s, args) => UpdateBatteryInfo(); _batteryMonitorTimer.Start(); // 启动时先获取一次初始电量 UpdateBatteryInfo(); }
- 修复原有PowerModeChanged事件的跨线程问题,SystemEvents的事件默认在后台线程触发,直接更新UI会抛出异常:
void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e) { // 切回UI线程执行更新操作 if (this.InvokeRequired) { this.Invoke(new Action(UpdateBatteryInfo)); return; } UpdateBatteryInfo(); }
- 资源释放,避免内存泄漏
private void Form_FormClosing(object sender, FormClosingEventArgs e) { SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; _batteryMonitorTimer?.Stop(); _batteryMonitorTimer?.Dispose(); }
方案2:封装自定义事件
如果要完全模拟事件触发的使用方式,可以在轮询逻辑的基础上封装自定义事件,当检测到电量变化时触发自定义的BatteryPercentageChanged事件,业务侧只需要订阅该事件即可,本质还是基于轮询实现,只是做了一层封装。
内容的提问来源于stack exchange,提问作者Taylor Abbott
相关产品推荐
相关产品推荐

