C# 挂起互操作COM对象时出现问题
我有一个应用程序,它使用COM互操作创建一个电子表格,该电子表格在客户机的Excel中打开。但是,如果我查看Task Manager,当用户关闭EXCEL时,EXCEL.exe进程似乎并不总是结束C# 挂起互操作COM对象时出现问题,c#,excel,com,interop,C#,Excel,Com,Interop,我有一个应用程序,它使用COM互操作创建一个电子表格,该电子表格在客户机的Excel中打开。但是,如果我查看Task Manager,当用户关闭EXCEL时,EXCEL.exe进程似乎并不总是结束 如果我保存工作簿并以编程方式关闭Excel,我只会使用Marshal.ReleaseComObject()进行清理,但由于我依赖于手动关闭程序,因此我不确定该怎么做。有什么建议吗?可能Excel.exe仍处于打开状态,因为用户在Excel应用程序的同一实例中打开了另一个文档。在这种情况下,您可能不应该
如果我保存工作簿并以编程方式关闭Excel,我只会使用
Marshal.ReleaseComObject()
进行清理,但由于我依赖于手动关闭程序,因此我不确定该怎么做。有什么建议吗?可能Excel.exe仍处于打开状态,因为用户在Excel应用程序的同一实例中打开了另一个文档。在这种情况下,您可能不应该终止Excel.exe进程
如果您确保关闭所有打开的文档,并释放所有创建的对象,那么为什么确保Excel.exe终止对您很重要?可能该进程正在为另一个应用程序或用户服务?可能有很多原因(包括Ran),但我在MapPoint(另一个具有COM接口的Microsoft应用程序)中经常看到的一个原因是,您必须确保清除所有对象引用,以便垃圾收集器可以清除它们。一个较低的对象挂起就足以阻止应用程序关闭并退出进程列表。Excel在其所有进程外对象释放之前无法终止。所以它只是隐藏了它的用户界面并继续运行。直到程序退出或将所有Excel对象引用设为空,并且终结器线程运行。退出你的计划将是一个显而易见的解决办法。或者,您可以强制终结器线程以以下方式运行:
GC.Collect();
GC.WaitForPendingFinalizers();
ReleaseComObject()很少工作,因为很容易忘记中间COM对象引用。就像工作簿[索引]一样,这是一个你看不到的枚举器。让GC自己做出决定将是更明智的选择,如果您继续运行和工作,那么这将发生。如果我使用以下命令打开Excel应用程序和工作簿:
Excel.Application app = new Excel.Application();
Excel.Workbook wb = app.Workbooks.Open(...);
然后在finally语句(或其他适当的关闭事件)中使用
wb.Close()
,app.Quit()
方法。这将清理Exel.exe进程。无需调用Marshall.ReleaseComObject
或GC方法。删除这些对象引用的最佳方法是什么?我应该使用ReleaseComObject()
?看起来Hans已经回答了。将引用设置为null。如果这还不够,请在完成时运行GC.Collect。NET通常能很好地处理COM(就像旧的VB6),您不需要太多地担心底层细节。GC.Collect()
和GC.WaitForPendingFinalizers()
似乎可以做到这一点。