如何在.NET中处理事件时释放所有的COM对象

我在C#中使用COM Excel应用程序类。 我处理了WorkbookBeforeClose 。 但是现在我无法正确释放COM对象。

请注意,在处理此事件之前,我已经正确地释放了COM对象,并且在注释那部分代码时,我的应用程序正常工作。

什么COM对象没有从内存中释放,以及如何正确释放它?

编辑:我做了什么:

 public void Init() { ... application = new Excel.Application(); application.WorkbookBeforeClose += new Excel.AppEvents_WorkbookBeforeCloseEventHandler(application_WorkbookBeforeClose); } ... void application_WorkbookBeforeClose(Excel.Workbook Wb, ref bool Cancel) { if (WorkbookBeforeClose != null) { ExcelCloseEventArgs args = new ExcelCloseEventArgs(); WorkbookBeforeClose(this, args); Cancel = args.Cancel; } else Cancel = false; } ... private void closeExcel() { try { if (workbook != null) { workbook.Close(false); } } catch (Exception e) { } finally { if (workbooks != null) Marshal.ReleaseComObject(workbooks); if (workbook != null) Marshal.ReleaseComObject(workbook); } try { if (application != null) { application.WorkbookBeforeClose -= handler; application.Quit(); Marshal.ReleaseComObject(application); Marshal.ReleaseComObject(handler); process.WaitForExit(); } } catch (Exception e) { throw; } finally { } workbook = null; workbooks = null; application = null; if (process != null && !process.HasExited) process.Kill(); if (threadCulture != null) Thread.CurrentThread.CurrentCulture = threadCulture; initialized = false; } 

应用程序暂停在行process.WaitForExit()

内存pipe理在.NET中是自动的。 显式调用Marshal.ReleaseComObject()是一个错误。 这不仅仅是因为当你这么做的时候,你很容易就会崩溃RCW,特别是因为引用计数通常是隐藏的。 索引和事件是棘手的。 一个丢失的ReleaseComObject调用就足以让它回退到垃圾收集器来处理它。 GC需要一些时间来解决释放内存(和引用计数)是一个function,而不是一个错误。

如果你确实希望COM服务器按需退出而不是让垃圾收集器处理它,那么将所有引用设置为null,取消订阅事件处理程序并调用GC.Collect()。 不需要ReleaseComObject调用。 查看这个博客文章的专业人士的见解。

我通过在closeExcel方法中修改这些代码行来修复我的代码:

 if (application != null) { application.WorkbookBeforeClose -= new Excel.AppEvents_WorkbookBeforeCloseEventHandler(application_WorkbookBeforeClose); application.Quit(); Marshal.ReleaseComObject(application); GC.Collect(); GC.WaitForPendingFinalizers(); process.WaitForExit(100); } 

我认为这个问题是关于垃圾收集的。 我的对象没有完全收集。