如何在C#中正确清理Excel interop对象,2012版

4
我正在用C#编写一个应用程序,它将通过互操作打开一个Excel电子表格(目前是2007版),进行一些操作,然后关闭。 "魔法" 部分并不简单,因此该应用程序将包含许多对Excel生成的许多COM对象的引用。
我以前写过这种应用程序(实际上已经写了太多次了),但我从未找到一种舒适,"好闻" 的与COM对象交互的方法。问题部分在于,尽管进行了大量研究,我仍然不完全理解COM,而且互操作包装器隐藏了许多可能不应该被隐藏的内容。社区中有如此多不同的、相互冲突的建议只会使情况变得更糟。
如果你从标题中看不出来,那么我已经做过我的研究。标题暗示了这篇文章:
如何正确清理Excel互操作对象? 该建议最初是在2008年提出的,当时非常有帮助和可靠(特别是“永远不要使用2个点与com对象”这一点),但现在似乎已经过时了。在2010年3月,Visual Studio团队发布了一篇博客文章,警告其他程序员:Marshal.ReleaseComObject被认为是危险的。该文章引用了两篇文章:cbrumme的WebLog > ReleaseComObject接口指针与运行时可调用包装器(RCW)之间的映射,暗示人们一直在错误地使用ReleaseComInterop(cbrumme:“如果您是使用少量COM对象的客户端应用程序,这些对象在您的托管代码中自由传递,您不应该使用ReleaseComObject”)。 是否有一个中等复杂度的应用程序示例,最好使用多个线程,能够成功地在内存泄漏(Excel在应用程序关闭后仍在后台运行)和InvalidComObjectExceptions之间进行导航?我正在寻找一种允许在创建它的上下文之外使用COM对象但仍然可以在应用程序完成后清理它的内存管理策略的混合体:一种有效跨越托管/非托管之间的内存管理策略。
参考文章或教程,讨论这个问题的正确方法,将是一个非常受欢迎的替代方案。我的最佳Google-fu努力返回了明显不正确的ReleaseComInterop方法。

更新:
(这不是一个答案)
我在发布后不久发现了这篇文章:
Jake Ginnivan的VSTO和COM互操作

我已经能够通过扩展方法实现他的“AutoCleanup”类包装COM对象的策略,并且对结果感到非常满意。虽然它并没有提供一种解决方案,允许COM对象跨越它们被创建的上下文边界并仍然使用ReleaseComObject函数,但至少提供了一个简洁易读的解决方案。

以下是我的实现:

class AutoCleanup<T> : IDisposable {

    public T Resource {
        get;
        private set;
    }

    public AutoCleanup( T resource ) {
        this.Resource = resource;
    }

    ~AutoCleanup() {
        this.Dispose();
    }

    private bool _disposed = false;
    public void Dispose() {
        if ( !_disposed ) {
            _disposed = true;
            if ( this.Resource != null && 
                 Marshal.IsComObject( this.Resource ) ) {
                Marshal.FinalReleaseComObject( this.Resource );
            } else if ( this.Resource is IDisposable ) {
                ( (IDisposable) this.Resource ).Dispose();
            }
            this.Resource = null;
        }
    }

}

static class ExtensionMethods {

    public static AutoCleanup<T> WithComCleanup<T>( this T target ) {
        return new AutoCleanup<T>( target );
    }

}

请将以下与编程有关的内容从英语翻译成中文。请仅返回翻译的文字内容,不要解释它。 - nawfal
2
@nawfal - 这不是一个答案,只是一个补充。 - JDB
1个回答

1

你知道NetOffice概念中的COM代理管理吗? NetOffice使用包装类来处理COM代理和IDisposable模式。 NetOffice保持代理的父子关系。当你释放一个工作表时,所有创建的子代理(单元格、样式等)也会被释放。你还可以使用特殊事件或静态属性来观察应用程序中打开代理的数量。

请查看此文档片段: http://netoffice.codeplex.com/wikipage?title=Tec_Documentation_English_Management

在教程文件夹中,你会发现一些解决COM代理管理问题的项目。


这是最有趣的答案。我没有尝试过,但基于解决方案的描述,我会接受它。 - JDB
在我的小测试中,这个程序可以正常工作并在完成后关闭了Excel。谢谢! - sonicbabbler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接