> Excel 2007 Hangs When Closing via .NET
> How to properly clean up Excel interop objects in C#
> How to properly clean up interop objects in C#
C#在使用它们后不会正确释放Excel COM对象的问题.这个问题主要有两个方向:
>当Excel不再使用时,请关闭Excel进程.
>请注意,首先明确分配用于变量的每个COM对象,并确保最终在每个对象上执行Marshal.ReleaseComObject.
有些人表示,2太乏味,总是有一些不确定性,无论你是否忘记在代码中的某些地方遵守这一规则.仍然1似乎很脏,容易出错,我也猜测在一个有限的环境下,试图杀死一个进程可能会引发安全错误.
所以我一直在想通过创建另一个模拟Excel对象模型的代理对象模型来解决问题2(对我而言,实现我实际需要的对象就足够了).原则如下:
>每个Excel Interop类都有它的代理,它包装该类的对象.
>该代理在其终结器中释放COM对象.
>代理模拟Interop类的接口.
>任何最初返回COM对象的方法都会更改为返回代理.其他方法简单地将实现委托给内部COM对象.
例:
public class Application { private Microsoft.Office.Interop.Excel.Application innerApplication = new Microsoft.Office.Interop.Excel.Application innerApplication(); ~Application() { Marshal.ReleaseCOMObject(innerApplication); innerApplication = null; } public Workbooks Workbooks { get { return new Workbooks(innerApplication.Workbooks); } } } public class Workbooks { private Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks; Workbooks(Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks) { this.innerWorkbooks = innerWorkbooks; } ~Workbooks() { Marshal.ReleaseCOMObject(innerWorkbooks); innerWorkbooks = null; } }
我的问题特别是:
谁发现这是一个坏主意,为什么?
谁找到这个gread的想法?如果是这样,为什么还没有人实施/发布这样的模型?这只是由于努力,还是我错过了这个想法的杀人问题?
>在终结器中是否不可能/不好/容易出错的ReleaseCOMObject? (我只看过把它放在一个Dispose()而不是一个finalizer中的提议 – 为什么?)
>如果方法有意义,有什么建议来改进吗?
解决方法
Is it impossible/bad/dangerous to do the ReleaseCOMObject in the destructor? (I’ve only seen proposals to put it in a Dispose() rather than in a destructor – why?)
建议不要将清理代码放在finalizer中,因为与C中的析构函数不同,它不是确定性地调用.在对象超出范围后不久可能会被调用.可能需要一个小时.它可能永远不会被调用.一般来说,如果要处理非托管对象,则应使用IDisposable模式,而不是终结器.
您链接的这个solution试图通过显式调用垃圾收集器并等待finalizer完成来解决这个问题.这一般不是一般推荐的,但是对于这种特定情况,有些人认为这是一个可以接受的解决方案,因为难以跟踪所有创建的临时非管理对象.但明确的清理是正确的方法.但是,由于这样做的困难,所以这个“黑客”可能是可以接受的.请注意,此解决方案可能优于您提出的想法.
如果您想要尝试明确地清理,“不要使用COM对象的两个点”指南将帮助您记住保留对每个您创建的对象的引用,以便在完成后清理它们.