C# 为什么FinalReleaseComObject会导致;(互批准程序)已停止工作“;?

C# 为什么FinalReleaseComObject会导致;(互批准程序)已停止工作“;?,c#,com,ms-word,interop,C#,Com,Ms Word,Interop,我正在尝试从Word文档中读取文本和图像并关闭它。问题是试图在Word没有遇到任何问题或创建多个WINWORD.exe实例的情况下关闭它。我的问题是,当我调用Marshal.FinalReleaseComObject(app)时在Word.ApplicationClass上,Word引发Windows提供的一般异常(“Word已停止工作”)。我已经阅读了中的许多解决方案并实施了这些建议,但我仍然有这个问题 这是我的密码。我只阅读了一页一个Word文件(您可能想跳到发生异常的“//Cleanup:

我正在尝试从Word文档中读取文本和图像并关闭它。问题是试图在Word没有遇到任何问题或创建多个WINWORD.exe实例的情况下关闭它。我的问题是,当我调用
Marshal.FinalReleaseComObject(app)时
Word.ApplicationClass
上,Word引发Windows提供的一般异常(“Word已停止工作”)。我已经阅读了中的许多解决方案并实施了这些建议,但我仍然有这个问题

这是我的密码。我只阅读了一页一个Word文件(您可能想跳到发生异常的“//Cleanup:”)

这种情况并不总是在我第一次读取文件时发生。当我读第二次或第三次时,我通常会发现错误


有什么方法可以防止错误显示吗?

在调用FinalReleaseComObject之前,您可以尝试检查是否存在错误。

您不应该使用
FinalReleaseComObject
,这是一个释放/删除您肯定知道的RCW的锤子。您是唯一的推荐人(在.NET中)

在这种情况下,您可以完全减少每个RCW、
doc
docs
app
上的引用计数,而不仅仅是从您拥有的引用中

请尝试改为
ReleaseComObject
,但请注意,如果仍有一个.NET枚举器处于活动状态、正在使用并连接到您从Word集合中释放的一个对象,则这可能同样糟糕


关闭文档、退出Word、将变量设置为
null
和GC'ing就足够了。根据编译器的不同,它可能会从堆栈中丢弃变量,并删除将它们设置为
null

的代码。鉴于此崩溃相当罕见,Word通常知道如何处理这种内存管理的重锤方法。然而,这是一种非常糟糕的做法。VisualStudio团队的最佳描述。值得一读的是,“沉默刺客”部分是最相关的

调用GC.Collect就足以释放所有COM引用,不需要额外的帮助。但是,如果您在运行程序时附加了调试器,则这将不起作用。解释了原因

要使GC.Collect()也在调试器中工作,需要在单独的方法中移动它,以便调试器无法保持引用的活动状态。这样做最容易:

private byte[] GetDocumentText(byte[] wordBytes, string path) {
   var retval = GetDocumentTextImpl(wordBytes, path);
   GC.Collect();
   GC.WaitForPendingFinalizers();
   return retval;
}

private byte[] GetDocumentTextImpl(byte[] wordBytes, string path) {
   // etc...
}

并将原始代码移到GetDocumentTextImpl()方法中。只需从代码中删除所有封送和GC调用,因为它们完全没有必要。而且很危险。

关于这个问题,你的另一个答案解释得很清楚。再加上办公室互操作反复出现的问题,这是黄金!汉斯,伟大的文章和回应。我仍然有一些问题,但我不认为它们与这个问题有直接关系,所以我为他们创建了一个单独的问题。谢谢
private byte[] GetDocumentText(byte[] wordBytes, string path) {
   var retval = GetDocumentTextImpl(wordBytes, path);
   GC.Collect();
   GC.WaitForPendingFinalizers();
   return retval;
}

private byte[] GetDocumentTextImpl(byte[] wordBytes, string path) {
   // etc...
}