检查物品是不是已被处置的正确方法
Posted
技术标签:
【中文标题】检查物品是不是已被处置的正确方法【英文标题】:Correct Method for checking if an item has been disposed检查物品是否已被处置的正确方法 【发布时间】:2014-04-23 10:28:19 【问题描述】:在 VB .net 中检查对象是否已被释放的正确语法是什么?
在我的例子中,公开声明的数据库连接 (dbLocal
) 由 USING 块处理,再次调用数据库连接会触发错误。
我已经尝试实现 .IsDisposed
代码 here 但声明需要一个 Get,我不完全确定如何添加。
一旦我可以检查它.isdisposed,重新创建公共对象的正确方法是什么?
数据库声明:
Public dbLocal As New SQLiteConnection("Data Source=" & Replace(Application.StartupPath, "\", "\\") & "\\database.db;FailIfMissing=True")
使用循环:
Using dbLocal
'Create Command & add parameters
Dim Typecmd As New SQLiteCommand(TypeSQLI, dbLocal)
With Typecmd.Parameters.Add("@id", DbType.String, 50, "id")
Typecmd.Parameters.Add("@description", DbType.String, 100, "description")
Typecmd.Parameters.Add("@sex", DbType.Int16, 1, "sex")
Typecmd.Parameters.Add("@master", DbType.String, 50, "master")
Typecmd.Parameters.Add("@size_min", DbType.String, 2, "size_min")
Typecmd.Parameters.Add("@size_max", DbType.String, 2, "size_max")
Typecmd.Parameters.Add("@size_half", DbType.Int16, 1, "size_half")
Typecmd.Parameters.Add("@lining", DbType.String, 2, "lining")
End With
Dim adapter As New SQLiteDataAdapter()
adapter.InsertCommand = Typecmd
Try
Dim iRowsInserted As Int32 = adapter.Update(typetable)
'Output result
LstProcessed.Items.Add(iRowsInserted & " records added.")
LstProcessed.TopIndex = LstProcessed.Items.Count - 1
Catch ex As Exception
MsgBox("Import error. " & Chr(13) & Chr(10) & "Check syntax of imported file (were there headers?).", MsgBoxStyle.Critical)
End Try
End Using
理想情况下,“IsDispose”函数会在进入 USING 循环之前检查数据库是否已关闭。
我添加了 IsDisposed 声明,如 MSDN 文章中所述,导致...
Public ReadOnly Property IsDisposed() As Boolean
Get
???
End Get
End Property
【问题讨论】:
发布一些代码。dbLocal
是什么? SqlConnection
?
没有通用的方法来获取已处置的对象并能够创建一个副本,就像该对象在处置之前一样。它可能已经执行了任意数量的清理,从而破坏了它在运行时保存的数据。 dispose 模式的全部意义在于,当 您 知道您不再需要此对象时,您调用 Dispose
。如果您遇到的情况是您有一个对象并且不确定它是否已被处理,那么您使用它是错误的。
正如我上面所说,一旦 VB 完成 USING 循环,似乎数据库连接正在关闭。基本上记录在here
如果你在Using
语句中放置一些东西,你就是在告诉系统“当我们退出这个Using
块时,我不再需要访问这个对象”。如果不是这样,那么不要使用using
语句。
【参考方案1】:
您不需要检查对象的处置情况。
理想情况下,您应该像这样将其包装在 Using 块中:
Using obj As New foo
'use your object
End Using
下次使用它时,将代码包装在另一个 Using 块中。
我认为您的问题不是在 Using 块的开头创建 New 对象。你可能想要这个:
Using dbLocal As New SQLiteConnection("Data Source=" & Replace(Application.StartupPath, "\", "\\") & "\\database.db;FailIfMissing=True")
'...
End Using
这里dbLocal
的范围仅适用于Using
块的生命周期。目前,您正在使用一个全局变量,该变量正在End Using
行中处理。
【讨论】:
干杯。显而易见的答案通常是最好的答案。【参考方案2】:一般来说,如果不知道某项是否已处置,则无法充分了解其状态,从而无法执行任何取决于其状态的操作。包含通知方法的类应该以可以在任何状态下安全调用它们的方式编写它们(当对象处于不关心通知的状态时,它应该简单地忽略通知)。在大多数情况下,模式:
if (!thing.IsDisposed)
thing.DoSomething();
会有意义,该模式应该在thing
本身的类中实现 [例如。因为BeginInvoke
通常用于通知控件他们可能正在监视的属性的更改,所以Control
应该(但没有)有一个TryBeginInvoke
方法,如果控件无法执行该方法,它将默默地什么也不做接受]。有时(就像Control.BeginInvoke
一样,人们不得不在没有这种方法的情况下苦苦挣扎,但通常唯一不知道是否已经处理过某事的情况是,如果某事可以在自己的控制之外被处理;在那种情况下,即使IsDisposed
返回 false,人们也可能不知道这种情况会持续多久。
【讨论】:
【参考方案3】:虽然 OP 的问题似乎是他们在不了解其含义的情况下使用 using 语句,但读者可能希望明确回答标题实际提出的问题。
很遗憾,答案是只能通过 try/catch 来判断,不幸的是,您必须捕获的异常取决于资源。就我个人而言,我认为这是 IDisposable 接口的失败,但已经完成的工作已经完成,并且正如已经提到的,无论如何,人们不知道它会持续多久。
大多数已处置的对象都会抛出 InvalidOperationException ,但这只是一个约定。除非您有相关对象的文档,否则您只能通过故意释放实例并尝试查看抛出的内容来确定。
【讨论】:
以上是关于检查物品是不是已被处置的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
MVC 3.0错误 HTTP 404您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检查以下 URL 并确保其拼写正确。