我以前写过这种应用程序(事实上已经太多次了)但是我从未找到过与COM对象交互的舒适,“好闻”的方法.问题部分在于,尽管进行了大量研究,我仍然不能完全理解COM,部分是因为互操作包装器隐藏了很多可能不应该隐藏的内容.事实上,来自社区的这么多不同的,相互矛盾的建议只会让事情变得更糟.
如果您无法从标题中分辨出来,我已经完成了我的研究.标题暗示了这篇文章:
How do I properly clean up Excel interop objects?
在2008年首次询问时,这个建议在当时非常有用且非常可靠(特别是“从不使用带有com对象的2个点”位),但现在看来已经过时了.在2010年3月,Visual Studio团队发布了一篇博客文章,警告其他程序员Marshal.ReleaseComObject [is] Considered Dangerous.文章提到了两篇文章cbrumme’s WebLog > ReleaseComObject和The mapping between interface pointers and runtime callable wrappers (RCWs),暗示人们一直错误地使用ReleaseComInterop(cbrumme:“如果你是一个客户端应用程序使用在托管代码中自由传递的适度数量的COM对象,不应使用ReleaseComObject“).
有没有人有一个中等复杂的应用程序的例子,最好使用多个线程,能够在内存泄漏(Excel在应用程序关闭后继续在后台运行)和InvalidComObjectExceptions之间成功导航?我正在寻找能够在创建它的上下文之外使用COM对象的东西,但是一旦应用程序完成它仍然可以清理它:内存管理策略的混合,可以有效地跨越托管/非管理鸿沟.
对于讨论这个问题的正确方法的文章或教程的引用将是一个非常受欢迎的替代方案.我最好的Google-fu努力已经返回了显然不正确的ReleaseComInterop方法.
更新:
(这不是答案)
发布后不久我发现了这篇文章:
VSTO and COM Interop by Jake Ginnivan
我已经能够通过扩展方法实现他在“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 ); } }
解决方法
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。