【发布时间】:2009-12-03 22:27:45
【问题描述】:
问题:
我想问一个问题以回复Mike Rosenblum's answer 至this question。问题是关于清理 Excel 互操作对象。建议的几种解决方案(例如,包装器,不使用多个点,终止 excel 进程),但我最喜欢 Mike Rosenblum's solution 解决这个问题(lengthy article about the topic)。
它基本上说的是,您不必太担心所有浮动的引用。你只保留一些主要的(如ApplicationClass、Workbook 和Worksheet)。您首先调用垃圾回收来清理所有浮动的对象,然后通过调用 Marshal.FinalReleaseComObject 显式清理您仍然拥有的主要引用(按重要性相反的顺序)。
现在我对此有两个问题。
第一:我如何确定我需要保留哪些对象的引用?在Mike Rosenblum's example 中,他只保留Ranges、Worksheets、Workbooks 和ApplicationClasses。
第二:如果对象比较多,如何确定清理的顺序(即“重要性顺序”)?
提前致谢。
更新 1:
MattC 建议,对于订单,唯一重要的是应用程序最后发布。尽管在我的reference 中有以下句子:“您还应该按重要性相反的顺序释放命名引用:首先是范围对象,然后是工作表、工作簿,最后是您的 Excel 应用程序对象。”意味着有更多的排序。
nobugz 建议将所有内容设置为null,然后进行垃圾收集就足够了,但这似乎与Mike Rosenblum's article 的以下引用相矛盾:“那么,您会认为您可以设置所有变量 = Nothing,然后在最后调用GC.Collect(),这有时确实有效。但是,Microsoft Office 应用程序对释放对象的顺序很敏感,不幸的是,设置变量 = Nothing 然后调用@ 987654342@不保证对象的释放顺序。”
更新 2:
一些额外的信息:
在我自己的应用程序中,我用图表做了很多事情。我正在设置很多属性等。据我所知,有很多地方可以创建新的 COM 对象。我试图确保我从不使用双点,并尝试在我完成的所有对象上调用Marshal.FinalReleaseComObject。我没有使用包装器方法,因为它会引入大量嵌套。EXCEL.exe 在我的应用程序完成工作后没有关闭。但是......当我告诉我的应用程序再次执行相同的工作时,它确实关闭了。当然,打开了一个新的EXCEL.exe,但没有关闭。现在我已经删除了所有Marshal.FinalReleaseComObject 调用,并且应用程序的工作方式完全相同。 EXCEL.exe 一直存在,直到我告诉我的应用程序重做工作,但随后新的 EXCEL.exe 启动并保留。
编辑:另外,当我告诉我的应用程序执行其他与 COM 无关的工作时,一段时间后 EXCEL.exe 消失了,但现在没有新的 EXCEL.exe 出现。
不知道我能从中得出什么结论......
【问题讨论】:
-
Nobugz 不一定与 Mike 签约(来自上述更新 1)。基本模式是... object = null;等等 Gc.waitforpendingfinalizers gc.collect Gc.waitforpendingfinalizers gc.collect Marshal.FinalReleaseCOMObject(object)
-
是的,我不是 100% 确定 NoBugz 的意思。他的意思是命令重要还是不重要? (我有点不在讨论范围内,所以我可能忽略了前面所说的内容)。
-
您应该以相反的重要性顺序释放对象的原因是,如果您在完成编辑属性和调用依赖子方法的方法之前释放父对象。在这种情况下,您可能会发现一个孤立的 com 对象,以及可能出现的奇怪症状,例如 ComException 或 InvalidCastExceptions。
标签: c# com garbage-collection excel-interop