Windows 11中UIAutomationClient.DLL疑似存在内存泄漏
问题分析与解决方案
问题现象
使用C#通过定时器反复调用AutomationElement.RootElement.FindAll获取桌面顶层窗口时,Windows 10环境下内存占用稳定,但Windows 11中内存持续增长。
原因推测
Windows 11的UI自动化(UIA)实现存在非托管资源泄漏:AutomationElementCollection及其包含的AutomationElement对象基于COM架构,.NET垃圾回收器无法及时识别并回收这些非托管资源,导致内存占用持续上升。Windows 10的UIA实现资源回收逻辑更完善,因此未出现该问题。
解决方法
1. 显式释放COM资源
在每次获取集合后,手动释放集合及其中所有AutomationElement对象的COM引用,确保非托管资源被及时回收:
修改回调函数如下:
static void Callback(object state) { AutomationElementCollection desktopChildren = null; try { desktopChildren = AutomationElement.RootElement.FindAll(TreeScope.Children, Condition.TrueCondition); // 若有业务逻辑可在此处执行 } finally { if (desktopChildren != null) { // 释放集合内每个元素的COM引用 foreach (AutomationElement element in desktopChildren) { System.Runtime.InteropServices.Marshal.ReleaseComObject(element); } // 释放集合本身的COM引用 System.Runtime.InteropServices.Marshal.ReleaseComObject(desktopChildren); } } }
2. 优化定时器调用频率(可选)
若业务场景允许,适当增大定时器间隔(例如从1000ms调整为2000ms),减少API调用频次,降低资源占用压力。
3. 强制触发垃圾回收(临时应急方案)
作为调试或临时应急手段,可在回调末尾触发垃圾回收,但长期使用可能影响程序性能:
static void Callback(object state) { AutomationElementCollection desktopChildren = null; try { desktopChildren = AutomationElement.RootElement.FindAll(TreeScope.Children, Condition.TrueCondition); } finally { if (desktopChildren != null) { foreach (AutomationElement element in desktopChildren) { System.Runtime.InteropServices.Marshal.ReleaseComObject(element); } System.Runtime.InteropServices.Marshal.ReleaseComObject(desktopChildren); } GC.Collect(); GC.WaitForPendingFinalizers(); } }
验证效果
修改代码后重新编译运行,观察Windows 11任务管理器的内存占用情况,内存应不再持续增长,保持稳定状态。
内容的提问来源于stack exchange,提问作者Deen
相关产品推荐
相关产品推荐

