我正在用C#編寫一個應用程序,它將通過interop打開一個Excel電子表格(2007年,現在),做一些魔術,然後關閉。 「魔術」部分是不平凡的,所以這個應用程序將包含很多對由Excel產生的COM對象的引用。我曾經寫過這種應用程序(事實上太多次了),但我從來沒有找到與COM對象交互的舒適「好味道」方法。問題的部分原因在於,儘管進行了大量的研究,但我仍然不完全理解COM,部分原因是互操作包裝器隱藏了很多可能不應該隱藏的東西。事實上,來自社區的許多不同的,相互矛盾的建議只會讓事情變得更糟。如何在C#中正確清理Excel互操作對象,2012版
如果你不能從標題中知道,我已經完成了我的研究。標題暗示了這個帖子:
How do I properly clean up Excel interop objects?
於2008年首次提出,建議在當時(尤其是「從不使用2點與COM對象」位)非常有幫助和固體,但現在看來已經過時了。在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方法。
UPDATE:
(這不是一個答案)
我發現這篇文章發佈後沒多久:
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);
}
}
請張貼作爲回答,這樣纔有助於未來的遊客 – nawfal
@ nawfal - 這不是一個答案。只是一個附錄。 – JDB