我正在尝试找出使用DataSet
/ DataTable
的最佳方法,然后进行适当的清理。
我对释放内存的原因感到有些疑惑。我用一个测试应用程序测试了我的理论,我在一个循环中多次填充相同的DataTable
并在3个强制GC收集后查看Windows的任务管理器以查找内存占用量。
我发现的是:
如果我没有拨打Clear
或Dispose
,或将DataTable
变量设置为Nothing
,则任务管理器中的最终内存消耗约为30k。
如果我只是将循环中的变量设置为Nothing
,则最终内存大约为15k。
问题:为什么将变量设置为Nothing
会产生影响?
如果我在循环中仅调用Dispose
方法,则最终内存大约为19k。
如果我在循环中仅调用Clear
,则最终内存大约为16.5k。事实上,即使在GC.Collect
。
如果有人能够分享在不再需要时使用和清理DataSet
的最佳方式,我将非常感激。
示例代码如下所示。
Imports System.Data.SqlClient;
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Test()
GC.Collect()
GC.Collect()
GC.Collect() 'Throw in one more
End Sub
Private Sub Test()
Dim oDA As SqlDataAdapter = Nothing
Dim oConn As SqlConnection = Nothing
Dim oCommand As SqlCommand = Nothing
Dim ods As DataSet = Nothing
Dim oDt As DataTable = Nothing
Try
oConn = New SqlConnection("Server=Myserv;Database=myDB;UserId=myuserid;Password=mypassword;")
oCommand = New SqlCommand("Select * from Users", oConn)
oConn.Open()
ods = New DataSet
oDA = New SqlDataAdapter(oCommand)
For i As Integer = 0 To 50
oDA.Fill(ods)
oDt = ods.Tables(0)
'oDt.Clear()
'oDt.Dispose()
oDt = Nothing
Next
Catch ex As Exception
MessageBox.Show(ex.ToString)
Finally
ods.Clear()
ods = Nothing
oConn.Close()
oDA = Nothing
End Try
End Sub
End Class
编辑:我正在寻找管理传递的DataSet
和/或DataTable
内存的最佳实践,其中创建方法不一定要清理内存。另外,为什么在函数中将对象/变量设置为Nothing
的方式不同于让它超出范围。
答案 0 :(得分:5)
“清理”数据的最佳方法是切换到Using
statement以获取实现IDisposable
1 的任何内容。实现此模式后,您将拥有最合理的内存使用量,用于您设计的数据结构。
Using oConn As New SqlConnection("Server=Myserv;Database=myDB;UserId=myuserid;Password=mypassword;")
oConn.Open()
Using oCommand As New SqlCommand("Select * from Users", oConn)
' other code as needed, wrap IDisposable in Using...EndUsing
End Using
End Using
这并不能保证您的数据结构本身具有内存效率,只要它们只在必要时保留资源。
<子> 1。是的,你有时候不能使用一个,但是如果你在不使用using语句的前提下工作,你会更好。
答案 1 :(得分:0)
“为什么在一个函数中设置任何东西都不同于让它超出范围?”
您已经访问了某些内容,因此在此之前它不符合GC的条件。
当GC发生时有点不确定:显然它会根据几个因素安排下一次调用(引用:http://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-33-CLR-GC-Part-1(视频))。
答案 2 :(得分:0)
使用任何必须在使用后释放的资源(包括DataTable或Dataset)的最佳方法是尽可能使用关键字Using。如果无法使用Using关键字,则应该执行与使用关键字相同的操作: 尝试 { } Catch(Exception ex) { } 最后 { object.dispose() }
根据msdn,任何实现IDisposable的对象都应该使用dispose方法释放资源。既可以使用Dataset,也可以使用 DataTable继承自实现IDisposable的MarshalByValueComponent,因此最好调用dispose方法。如果有 是任何不实现IDisposable方法的资源,那么您可以实现IDisposable接口并覆盖dispose 处理方法和资源清理方法。通过将DataSet或DataTable设置为null,您只需删除 最后将由垃圾收集器收集的引用。但使用dispose方法是更好的方法。你没有 显式调用GC.Collect方法,因为垃圾收集器通常在后台和内存中运行 如果低于某个阈值(由编译器确定),它将释放这些资源使用的内存。欲了解更多信息,请 请参阅垃圾收集(http://msdn.microsoft.com/en-us/library/0xy59wtx(v=vs.110).aspx)