加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 使用Wrapper对象来正确清理excel的互操作对象

发布时间:2020-12-15 17:37:18 所属栏目:百科 来源:网络整理
导读:所有这些问题: 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 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对象的两个点”指南将帮助您记住保留对每个您创建的对象的引用,以便在完成后清理它们.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读