作者:南方的狼1975 | 来源:互联网 | 2023-05-17 18:10
使用C#.NET4.0我公司的应用程序使用资源锁定器来保持记录不被同时编辑.我们使用数据库来存储锁的开始时间以及获取锁的用户.这导致在资源锁定器上执行以下(奇怪的?)dispose
使用C#.NET 4.0
我公司的应用程序使用资源锁定器来保持记录不被同时编辑.我们使用数据库来存储锁的开始时间以及获取锁的用户.这导致在资源锁定器上执行以下(奇怪的?)dispose,这恰好是从析构函数调用的:
protected virtual void Dispose(bool disposing)
{
lock (this)
{
if (lockid.HasValue)
{
this.RefreshDataButtOnAction= null;
this.ReadOnlyButtonAction= null;
try
{
**Dictionary parameters = new Dictionary();
parameters.Add("@lockID", lockid.Value);
parameters.Add("@readsToDelete", null);
Object returnObject = dbio2.ExecuteScalar("usp_DeleteResourceLockReads", parameters);**
lockid = null;
}
catch (Exception ex)
{
Logger.WriteError("ResourceLockingController", "DeleteResourceLocks", ex);
}
finally
{
((IDisposable)_staleResourcesForm).Dispose();
_staleResourcesForm = null;
}
}
}
}
我担心粗体部分我们因为从数据库调用中记录了奇怪的“Handle is not initialized”异常.我在其他地方读到在Finalize()期间创建新对象是不安全的,但同样的规则是否适用于dispose()?在Dispose()期间是否有任何可能的副作用伴随创建新对象?
解决方法:
which happens to be called from a destructor
这是真正的问题.您不能假设* dbio2“对象本身尚未最终确定.最终化顺序在.NET中不具有确定性.结果看起来很像您描述的,dbase提供程序使用的内部句柄将被释放,因此”处理未初始化“预期异常.或者dbio2对象已经被处理掉了.
这在程序退出时尤其可能出错.当终结器线程的2秒超时时,你也会遇到问题,dbase操作可以轻松获得更多.
你根本无法依靠终结器来为你做这件事.您必须检查disposing参数,并且当它为false时不调用dbio2.ExecuteScalar()方法.这可能也结束了析构函数的用处.