使用Wrapper对象来正确清理Excel互操作对象

所有这些问题:

  • 通过.NET关闭时Excel 2007挂起
  • 如何在C#中正确清理Excel互操作对象
  • 如何正确清理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;
        }
    }
    

    我对你的问题特别是:

  • 谁发现这是一个糟糕的主意,为什么?
  • 谁发现这是一个重要的想法? 如果是这样,为什么还没有人实施/发布这样的模型呢? 这是否只是由于努力,还是我错过了这个想法的杀戮问题?
  • 终结器中的ReleaseCOMObject不可能/不好/容易出错? (我只看到了将它放入Dispose()而不是终结器的提议 - 为什么?)
  • 如果方法有意义,有什么建议可以改进它?

  • 在析构函数中执行ReleaseCOMObject是不可能/不好/危险的吗? (我只看到了将它放入Dispose()而不是析构函数的建议 - 为什么?)

    建议不要将清理后的代码放入终结器中,因为与C ++中的析构函数不同,它不会被确定性地调用。 它可能会在对象超出范围后立即调用。 这可能需要一个小时。 它可能永远不会被调用。 一般来说,如果你想处置非托管对象,你应该使用IDisposable模式而不是终结器。

    您链接的此解决方案试图通过显式调用垃圾回收器并等待终结器完成来解决该问题。 这通常不被推荐,但对于这种特殊情况,有些人认为这是一个可接受的解决方案,因为难以跟踪所有创建的临时非托管对象。 但明确清理是正确的做法。 然而鉴于这样做的困难,这种“黑客”可能是可以接受的。 请注意,此解决方案可能比您提出的想法更好。

    相反,如果您想要明确清理,“不要在COM对象中使用两个点”指南将帮助您记住为每个创建的对象保留一个引用,以便在完成后清理它们。


    我们使用MSDN杂志中描述的LifetimeScope类。 使用它可以很好地清理对象,并且可以很好地处理我们的Excel导出。 代码可以在这里下载,也包含杂志文章:

    http://lifetimescope.codeplex.com/SourceControl/changeset/changes/1266


    看看我的项目MS Office for .NET。 通过本机VB.NET后期绑定功能解决了referencich包装对象和本地对象的问题。

    链接地址: http://www.djcxy.com/p/35647.html

    上一篇: Using Wrapper objects to Properly clean up excel interop objects

    下一篇: Releasing temporary COM objects