为啥此代码会导致 Excel 无法正常关闭?

Posted

技术标签:

【中文标题】为啥此代码会导致 Excel 无法正常关闭?【英文标题】:Why does this code cause Excel to not close properly?为什么此代码会导致 Excel 无法正常关闭? 【发布时间】:2011-06-25 06:43:09 【问题描述】:

为什么这行代码会导致 Excel 不退出?

Excel.Range range = (Excel.Range)ws.Cells[1,1];

如果是因为强制转换,那么这段代码不会导致同样的问题吗?

Excel.Worksheet ws = (Excel.Worksheet)wb.ActiveSheet;

我试过了。但这有效。 Excel 将关闭。

如果我使用此代码。 Excel 关闭。

Excel.Range range = ws.get_Range("A1","A1");

那么有什么区别呢?是的,我知道有一百万个“如何正确关闭 Excel”线程。但由于这是一个问题而不是答案,我决定问一个新问题而不是问其他人的问题。

这是我的代码。但当然还有其他代码。我只是注释掉所有内容并慢慢尝试哪些行导致 Excel 无法关闭。我意识到即使不使用垃圾收集器,Excel 仍然会关闭。我不想用大锤来关闭 Excel。

谢谢。

Excel.Application objExcel = new Excel.Application();
Excel.Workbooks wbs = objExcel.Workbooks;
Excel.Workbook wb = wbs.Open(saveFileDialog1.FileName, Type.Missing,  Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Excel.Worksheet ws = (Excel.Worksheet)wb.ActiveSheet;
//Excel.Range range = (Excel.Range)ws.Cells[1,1];
Excel.Range range = ws.get_Range("A1","A1");

FinalReleaseAnyComObject(range);
FinalReleaseAnyComObject(ws);
wb.Close(Type.Missing, Type.Missing, Type.Missing);
FinalReleaseAnyComObject(wb);
FinalReleaseAnyComObject(wbs);
objExcel.Quit();
FinalReleaseAnyComObject(objExcel);

目前我已经尝试过 objExcel、wbs、wb 和 ws。这 4 个对象不会造成问题。

private static void FinalReleaseAnyComObject(object o)

    Marshal.FinalReleaseComObject(o);
    o = null;

我知道你也不能重用这个变量。

Excel.Range range = ws.get_Range("A1","G1");
range = ws.get_Range("A1", "A1");

这也会导致 Excel 无法正常关闭。而是使用它。

Excel.Range range = ws.get_Range("A1","G1");
FinalReleaseAnyComObject(range);
range = ws.get_Range("A1", "A1");

【问题讨论】:

@user:关闭,你的意思是崩溃吗?看来强制转换操作不应该刻意关闭Excel。 @p.campbell 关闭,我的意思是正确关闭 Excel。 Excel 或 COM 对象可能存在无法正确关闭的众所周知的问题。即即使在我调用 objExcel.quit() 之后,Excel 进程仍将保留在任务管理器中。 【参考方案1】:

有一个隐藏的 Range 接口指针,你看不到,Cells 属性返回它。然后将索引器表达式应用到它,取消引用该 Range 的默认 Item 属性。获取另一个 Range。

这就是为什么尝试自己管理 COM 接口指针是一个非常糟糕的主意。相信垃圾收集器总是会做对。 GC.Collect() 和 GC.WaitForPendingFinalizers() 如果你真的,真的想让它按需退出。请务必阅读 this answer 以了解为什么在调试程序时这并不总是按预期工作。

【讨论】:

听说垃圾收集器很贵?不太确定,因为我已经读过了。 刚刚试过这个“Excel.Range range = (Excel.Range)ws.Cells[1,1];”与垃圾收集器一起工作!那么哪个更好呢?单元格还是 get_Range?我应该完全避免 GC 吗? 美丽的解释汉斯。 user607455,不,Hans 说清理 COM 对象时必须使用 GC。没有避免它。有关更详细的讨论,请参见此处:***.com/questions/158706/… @user607455,是的,当然你可以不使用 GC 来这样做,但是你会在幕后创建你不知道的对象,这是非常现实的风险。在大中型项目中,这种可能性几乎可以肯定。从长远来看,经验将表明强制 GC.Collect() 和 GC.WaitForPendingFinalizers() 是最好的。当然,这只是我的观点,但我在这方面有丰富的经验。 (另见:***.com/questions/158706/…)

以上是关于为啥此代码会导致 Excel 无法正常关闭?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这段代码会导致访问不正确? [关闭]

为啥此代码无法将 lista 识别为列表? [关闭]

为啥此代码会给出错误 Expected ',' 分隔符? [关闭]

win10为啥关闭system

为啥idea会弹出一个错误,叉掉导致idea关闭

为啥路由器桥接成功不能上网