Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#,2012版中正确清理Excel互操作对象_C#_.net 3.5_Marshalling_Com Interop_Excel Interop - Fatal编程技术网

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

如何在C#,2012版中正确清理Excel互操作对象,c#,.net-3.5,marshalling,com-interop,excel-interop,C#,.net 3.5,Marshalling,Com Interop,Excel Interop,我正在用C#编写一个应用程序,它将通过互操作打开一个Excel电子表格(现在是2007年),执行一些魔术,然后关闭。“魔力”部分非常重要,因此此应用程序将包含对Excel生成的许多COM对象的许多引用 我以前写过这种应用程序(事实上已经很多次了),但我从来没有找到一种舒适的“好味道”方法来与COM对象交互。问题部分在于,尽管进行了重要的研究,但我仍然不能完全理解COM,部分在于互操作包装器隐藏了很多可能不应该隐藏的内容。社会上有这么多不同的、相互矛盾的建议,这只会使情况变得更糟 如果你看不出标题

我正在用C#编写一个应用程序,它将通过互操作打开一个Excel电子表格(现在是2007年),执行一些魔术,然后关闭。“魔力”部分非常重要,因此此应用程序将包含对Excel生成的许多COM对象的许多引用

我以前写过这种应用程序(事实上已经很多次了),但我从来没有找到一种舒适的“好味道”方法来与COM对象交互。问题部分在于,尽管进行了重要的研究,但我仍然不能完全理解COM,部分在于互操作包装器隐藏了很多可能不应该隐藏的内容。社会上有这么多不同的、相互矛盾的建议,这只会使情况变得更糟

如果你看不出标题,我已经做了研究。标题暗指这篇文章:

2008年第一次被问到这个问题时,这个建议真的很有帮助而且很可靠(特别是“永远不要在com对象中使用2点”这一点),但现在似乎已经过时了。2010年3月,VisualStudio团队发布了一篇博客文章,警告其他程序员。这篇文章引用了两篇文章,并指出人们一直以来都在错误地使用ReleaseComInterop(cbrumme:“如果您是一个客户端应用程序,使用的COM对象数量不多,并且在托管代码中自由传递,那么您不应该使用ReleaseComObject”)

是否有人拥有一个中等复杂的应用程序示例,最好使用多个线程,能够成功地在内存泄漏之间导航(应用程序关闭后Excel继续在后台运行)和InvalidComObjectExceptions?我正在寻找一种允许COM对象在创建时的上下文之外使用,但在应用程序完成后仍然可以清理的东西:一种混合的内存管理策略,可以有效地跨越托管/非托管的界限

参考讨论此问题正确方法的文章或教程将是一个非常受欢迎的选择。我在谷歌fu上的努力回报了显然不正确的ReleaseComInterop方法


更新:
(这不是答案)
我在发布后不久发现了这篇文章:

我已经能够通过一个扩展方法实现他在“自动清理”类中包装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 );
    }

}
类自动清理:IDisposable{
公共旅游资源{
得到;
私人设置;
}
公共自动清理(T资源){
这个。资源=资源;
}
~AutoCleanup(){
这个。Dispose();
}
private bool_disposed=false;
公共空间处置(){
如果(!\u已处置){
_这是真的;
if(this.Resource!=null&&
Marshal.IsComObject(this.Resource)){
封送.finalEleaseComObject(this.Resource);
}else if(此.Resource可识别){
((IDisposable)this.Resource).Dispose();
}
this.Resource=null;
}
}
}
静态类扩展方法{
使用ComCleanup的公共静态自动清理(此T目标){
返回新的自动清理(目标);
}
}

您现在了解了用于COM代理管理的NetOffice概念吗? NetOffice对com代理和IDisposable模式使用包装类。 NetOffice保留代理的父->子关系。dispose一个工作表,并且从实例(单元格、样式)中创建的所有子项也被释放。您还可以使用特殊事件或静态属性来观察应用程序中打开的代理的计数

只需查看此文档片段:


您可以在教程文件夹中找到一些用于com代理管理的showstopper项目

请将其作为答案发布,以便对未来有所帮助visitors@nawfal-这不是答案。只是一个附录。这是最有趣的答案。我还没有试过,但我会接受它作为一个基于编写的解决方案。在我的小测试中,它工作正常,完成后关闭Excel。谢谢