ehh*_*ehh 11 .net c# vb.net com excel
这是一个非常常见的问题,我决定问这个问题,因为这个问题在今天可能会有不同的答案.希望这些答案有助于理解使用COM对象的正确方法.就个人而言,在对此主题发表不同意见后,我感到非常困惑.
在过去的5年中,我曾经使用COM对象,规则对我来说非常清楚:
你们中的一些人在阅读完最后一行后可能会感到沮丧,这就是我所知道的如何正确创建/发布Com对象,我希望能得到更清晰无误的答案.
以下是我在这个主题上找到的一些链接.他们中的一些人告诉他们需要调用ReleaseComObject而其中一些不需要.
"...在VSTO场景中,您通常不必使用ReleaseCOMObject......."
"...您应该使用此方法释放包含引用的基础COM对象......"
更新:
这个问题被标记为过于宽泛.根据要求,我将尝试简化并提出更简单的问题.
Gov*_*ert 19
.NET/COM互操作设计精良,工作正常.特别是,.NET垃圾收集器正确跟踪COM引用,并且当它们没有剩余的运行时引用时将正确释放COM对象.通过调用干扰COM对象的引用计数,Marshal.ReleaseComObject(...)或者Marshal.FinalReleaseComObject(...)是一种危险但常见的反模式.不幸的是,一些不好的建议来自微软.
您的.NET代码可以正确地与COM交互,同时忽略所有5个规则.如果确实需要触发不再从运行时引用的COM对象的确定性清理,则可以安全地强制GC(并可能等待终结器完成).否则,您不必在代码中执行任何特殊操作来处理COM对象.
有一个重要的警告,可能有助于混淆垃圾收集器的作用.在调试.NET代码时,局部变量人为地将其生命周期延长到方法的末尾,以支持在调试器下观察变量.这意味着您可能仍然具有对COM对象的托管引用(因此GC不会清理),而不仅仅是期望表单只是查看代码.此问题的一个很好的解决方法(仅在调试器下发生)是从GC清理调用中拆分COM调用的范围.
例如,这里有一些与Excel交互的C#代码,并且可以正常清理.您可以粘贴到控制台应用程序中(只需添加对Microsoft.Office.Interop.Excel的引用):
using System;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
namespace TestCsCom
{
class Program
{
static void Main(string[] args)
{
// NOTE: Don't call Excel objects in here...
// Debugger would keep alive until end, preventing GC cleanup
// Call a separate function that talks to Excel
DoTheWork();
// Now let the GC clean up (repeat, until no more)
do
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
while (Marshal.AreComObjectsAvailableForCleanup());
}
static void DoTheWork()
{
Application app = new Application();
Workbook book = app.Workbooks.Add();
Worksheet worksheet = book.Worksheets["Sheet1"];
app.Visible = true;
for (int i = 1; i <= 10; i++) {
worksheet.Cells.Range["A" + i].Value = "Hello";
}
book.Save();
book.Close();
app.Quit();
// NOTE: No calls the Marshal.ReleaseComObject() are ever needed
}
}
}
Run Code Online (Sandbox Code Playgroud)
您将看到Excel进程正确关闭,表明所有COM对象都已正确清理.
VSTO不会改变任何这些问题 - 它只是一个包装和扩展本机Office COM对象模型的.NET库.
关于这个问题存在很多虚假信息和混淆,包括MSDN和StackOverflow上的许多帖子.
什么最终说服我仔细看看并找出正确的建议是这篇文章https://blogs.msdn.microsoft.com/visualstudio/2010/03/01/marshal-releasecomobject-considered-dangerous/与找到在StackOverflow答案的调试器下保持活动引用的问题.
此一般指导的一个例外是COM对象模型要求以特定顺序释放接口.此处描述的GC方法无法控制GC释放COM对象的顺序.
我没有提及是否会违反COM合同.通常,我希望COM层次结构使用内部引用来确保正确管理对序列的任何依赖性.例如,在Excel的情况下,可以期望Range对象保持对父Worksheet对象的内部引用,以便对象模型的用户不需要显式保持两者都存活.
在某些情况下,即使Office应用程序对释放COM对象的顺序也很敏感.一个案例似乎是使用OLE嵌入时 - 请参阅https://blogs.msdn.microsoft.com/vsofficedeveloper/2008/04/11/excel-ole-embedding-errors-if-you-have-managed-add -in-下沉应用事件合的Excel-2 /
因此,如果对象以错误的顺序发布,则可能会创建一个COM对象模型失败,并且与这种COM模型的互操作将需要更多的关注,并且可能需要手动干涉引用.
但是对于与Office COM对象模型的一般互操作,我同意VS博客文章称为"Marshal.ReleaseComObject - 一个伪装成解决方案的问题".
| 归档时间: |
|
| 查看次数: |
2041 次 |
| 最近记录: |