为什么在关闭表单之前调用 FormDeactivate?

B. *_*non 2 c# excel-interop winforms-interop winforms

我有一个使用 Excel Interop 生成 Excel 电子表格的 Winforms 应用程序。

当我尝试以这种方式保存工作表时:

_xlBook.SaveAs(filename, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Run Code Online (Sandbox Code Playgroud)

...它会失败,告诉我,“ System.Runtime.InteropServices.InvalidComObjectException 未处理 HResult=-2146233049 Message=COM 对象已与其底层 RCW 分离,无法使用。

不过,这没有多大意义——我并没有对线程之类的东西做任何花哨的事情;这是一个非常简单的香草实用程序。代码中唯一引用 _xlBook 的其他地方是:

1)

private Excel.Workbook _xlBook;
Run Code Online (Sandbox Code Playgroud)

2)

_xlBook = _xlApp.Workbooks.Add(Type.Missing);
Run Code Online (Sandbox Code Playgroud)

3)

_xlSheets = _xlBook.Worksheets;
_xlSheet = (Excel.Worksheet)_xlSheets.Item[1];
Run Code Online (Sandbox Code Playgroud)

4)

_xlBook.Close(false);
Marshal.ReleaseComObject(_xlBook);
Run Code Online (Sandbox Code Playgroud)

_xlBook 被处理的最后一部分是从表单的 Deactivate 事件调用的,它是:

private void FormMain_Deactivate(object sender, EventArgs e)
{
    DeinitializeExcelObjects();
}
Run Code Online (Sandbox Code Playgroud)

问题是(我在所有引用 _xlBook 的地方放置断点后发现的)FormMain_Deactivate() 在 _xlBook.SaveAs() 被调用之前被调用,当点击“运行”按钮时调用。

一旦我在 FormMain_Deactivate() 中注释掉对 DeinitializeExcelObjects() 的调用,并在调用 _xlBook.SaveAs() 之后立即调用它,它就可以正常工作 - 创建和保存文件时没有任何错误消息。

那么为什么在关闭表单之前调用 FormDeactivate 呢?如果这以某种方式“按照设计”,则该事件的名称非常错误。

Ken*_*ite 5

你把代码放在错误的地方。:-) 您似乎误解了激活和停用的含义(至少就 Windows 而言)。

每当激活不同的窗口时就会发生停用,并且很明显,当您的表单被销毁时,另一个窗口必须变为活动状态,即使该窗口是 Windows 桌面。FormDeactivate可以被多次调用(例如当用户切换到不同的应用程序,甚至是您自己的应用程序中的不同窗口时)。需要注意的是,这也适用于激活FormActivate也可以多次触发。

如果您希望代码在表单关闭时运行,请将其放在FormClose事件处理程序中。