C#中将eventViewer赋值为null引发资源泄露该如何解决?
问题根因
XEEventViewer属于非托管资源包装类,实现了IDisposable接口,单纯将引用赋值为null只会断开引用和对象的关联,既不会触发GC立刻回收底层非托管资源,也不会主动调用内置的资源释放逻辑。- 先将
eventViewer置为null再调用Dispose属于逻辑错误:对象引用已经被清空,无法访问到原对象的释放方法,自然无法完成资源释放。 - 编译器抛出的覆盖报错,就是检测到你在未释放
eventViewer指向的非托管资源时,直接将引用赋值为null,导致没有可用引用能够触发资源释放逻辑,因此判定为资源泄露风险。
修复方案
优先使用C#官方推荐的using语法自动管理可释放资源,using作用域结束后会自动调用Dispose方法,即便代码执行过程中抛出异常也能保证资源正常释放,修改后的代码如下:
for (int i = 0; i < auditList.Count; i++) { audit = (XEAudit)auditList[i]; using (XEEventViewer eventViewer = audit.GetEventViewer()) { if (eventViewer != null) { while (eventViewer.NextEvent()) { if ((eventViewer.GetSeverity() == "Normal") || (eventViewer.GetSeverity() == "Critical")) validationFailed = true; break; } if (validationFailed == true) { StandardException innerException = traverseDN(OutermostException); OutermostException = innerException; } } } }
如果使用C# 8及以上版本,可以使用更简洁的using声明语法:
for (int i = 0; i < auditList.Count; i++) { audit = (XEAudit)auditList[i]; using XEEventViewer eventViewer = audit.GetEventViewer(); if (eventViewer != null) { while (eventViewer.NextEvent()) { if ((eventViewer.GetSeverity() == "Normal") || (eventViewer.GetSeverity() == "Critical")) validationFailed = true; break; } if (validationFailed == true) { StandardException innerException = traverseDN(OutermostException); OutermostException = innerException; } } }
如果因特殊场景无法使用using语法,也可以手动在finally块中调用Dispose,保证异常场景下资源也能正常释放:
for (int i = 0; i < auditList.Count; i++) { audit = (XEAudit)auditList[i]; XEEventViewer eventViewer = null; try { eventViewer = audit.GetEventViewer(); if (eventViewer != null) { while (eventViewer.NextEvent()) { if ((eventViewer.GetSeverity() == "Normal") || (eventViewer.GetSeverity() == "Critical")) validationFailed = true; break; } if (validationFailed == true) { StandardException innerException = traverseDN(OutermostException); OutermostException = innerException; } } } finally { eventViewer?.Dispose(); } }
内容的提问来源于stack exchange,提问作者Ram Mehta
相关产品推荐
相关产品推荐

