当有人使用任务管理器结束已实例化COM对象的.NET进程时,AFAIK无法在Marshal.FinalReleaseComObject
,try {} finally {}
或事件处理中调用using {}
块。
下次启动应用程序时,COM对象处于不可用状态,我需要重启机器才能使其再次运行。
我使用Marshal.BindToMoniker
来实例化对象。
我做错了什么,有什么我错过的吗?
我尝试了赛义德的建议,但它没有用
private const int WM_CLOSE = 0x0010;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_CLOSE)
{
logger.Info("WM_CLOSE");
Marshal.FinalReleaseComObject(comObject);
}
base.WndProc(ref m);
}
答案 0 :(得分:1)
您可能不需要。当垃圾收集器到处释放内存时,它会检查对象是否有一个尚未被调用的Dispose()方法。如果尚未调用Dispose()方法,它将调用它。
我在一个控制台应用程序中对此进行测试,并在我的Dispose功能中发出3个扬声器。退出应用程序后,无需在对象上调用Dispose,大约需要30秒才能听到3声嘟嘟声。时间是决定性的。
当然,必须正确编码对象。
您是否尝试在关机后立即运行该应用程序?为什么不等几分钟看它是否有效?
编辑:我假设您在Dispose函数中有Marshal.FinalReleaseComObject。
答案 1 :(得分:1)
任务管理器正在使用本地等效的Process.Kill
(或者可能更强大的东西)。请注意文档中的这个叙述:
Kill
强制终止流程,而CloseMainWindow
仅请求终止。...
调用
CloseMainWindow
发送请求以关闭主窗口,该窗口在格式良好的应用程序中...
和
如果您拨打
Kill
,则流程编辑的数据或分配给流程的资源可能会丢失。Kill
导致流程异常终止,只应在必要时使用。
简而言之,在程序代码中没有什么可以真正做到的,以防止这种情况 - 插头已被拉动。不会发送任何窗口消息。