调用SendMessage关闭屏幕后C# .NET 4.8应用在UpBoard上冻结如何解决
根因分析
- UpBoard作为工控单板默认开启了eDP显示端口与主板电源管理的联动策略,调用
SC_MONITORPOWER关屏指令时,会连带触发CPU进入深度C状态、非核心进程调度挂起的低功耗逻辑,普通消费级笔记本的显示电源与系统调度是独立设计,因此不会触发该问题。 - Windows 10 Enterprise LTSC 1809版本自带的UpBoard硬件适配驱动存在缺陷,会将系统API发起的关屏操作识别为用户主动闲置状态,进而冻结后台进程的执行,点亮屏幕后才会恢复调度。
- 你使用的eDP接口的电源信号直接与主板PCH电源管理模块绑定,相比HDMI、DP等外接显示接口,电源事件的联动优先级更高,关屏信号会直接触发生态的电源状态降级。
解决方案
1. 调整BIOS电源配置(优先级最高,改动最小)
开机按Del进入UpBoard的BIOS设置界面,找到Power Management菜单做如下修改:
- 关闭
DP/eDP Power Saving Mode选项 - 将
CPU C State Support限制为C1级别或直接关闭 - 将
PCIe Link Power Management设置为Maximum Performance
修改后保存重启即可生效。
2. 修改Windows系统电源策略
打开当前使用的电源计划的高级设置界面,做如下调整:
- 「硬盘」→「在此时间后关闭硬盘」设置为0(从不)
- 「PCI Express」→「链接状态电源管理」所有子项设置为「关闭」
- 「处理器电源管理」→「最小处理器状态」设置为100%,「系统散热策略」设置为主动
调整完成后以管理员身份运行命令提示符,执行如下命令禁用显示调光联动:
powercfg /setacvalueindex SCHEME_CURRENT SUB_VIDEO VIDEODIMMING 0 powercfg /setactive SCHEME_CURRENT
3. 优化应用代码逻辑
方案3.1 调用SetThreadExecutionState阻止系统挂起
在调用关屏代码前,先调用该API告知系统当前进程需要持续运行,避免被冻结,代码示例如下:
[FlagsAttribute] public enum EXECUTION_STATE : uint { ES_AWAYMODE_REQUIRED = 0x00000040, ES_CONTINUOUS = 0x80000000, ES_SYSTEM_REQUIRED = 0x00000001 } [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags); // 关屏前执行 SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_AWAYMODE_REQUIRED); // 原有屏幕关闭逻辑 SendMessage(-1, WM_SYSCOMMAND, (IntPtr) SC_MONITORPOWER, (IntPtr) newState);
方案3.2 替换屏幕关闭实现方式
放弃SC_MONITORPOWER系统关屏指令,改为直接调用Windows显示配置API将eDP屏幕的背光亮度调整为0,不会触发系统级电源事件,从根源避免进程冻结。
4. 升级硬件驱动
升级适配Windows 10 LTSC 1809的UpBoard芯片组驱动、核显驱动、电源管理驱动,旧版本驱动存在的关屏联动冻结进程的缺陷已在后续版本修复。
内容的提问来源于stack exchange,提问作者Paweł Kruczek
相关产品推荐
相关产品推荐

