.net 数据集和内存泄漏
我试图找出使用.net 数据集和内存泄漏,.net,vb.net,memory-management,memory-leaks,dataset,.net,Vb.net,Memory Management,Memory Leaks,Dataset,我试图找出使用数据集/数据表的最佳方法,并在之后进行适当清理 我有点困惑是什么导致记忆被释放。我用一个测试应用程序测试了我的理论,在这个测试应用程序中,我在一个循环中多次填充相同的DataTable,并在3次强制GC收集之后查看Windows任务管理器的内存占用情况 我发现: 如果我没有调用Clear或Dispose,或将DataTable变量设置为Nothing,任务管理器中的最终内存消耗大约为30k 如果我只是在循环内将变量设置为Nothing,则最终内存约为15k。 问题:为什么将变量设置
数据集
/数据表
的最佳方法,并在之后进行适当清理
我有点困惑是什么导致记忆被释放。我用一个测试应用程序测试了我的理论,在这个测试应用程序中,我在一个循环中多次填充相同的DataTable
,并在3次强制GC收集之后查看Windows任务管理器的内存占用情况
我发现:
Clear
或Dispose
,或将DataTable
变量设置为Nothing
,任务管理器中的最终内存消耗大约为30kNothing
,则最终内存约为15k。问题:为什么将变量设置为
Nothing
会产生影响Dispose
方法,那么最终的内存大约是19kClear
,那么最终的内存大约是16.5k。事实上,即使在GC.Collect
之后,它也没有改变DataSet
s的最佳方式,我将不胜感激
示例代码如下所示
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
s和/或DataTable
s内存的最佳实践,其中创建方法不一定负责清理内存。此外,为什么在函数中将对象/变量设置为“Nothing”(无)(无))与让其超出作用域不同。最好的“清理”数据的方法是,对于实现了IDisposable
1的任何对象,都切换到a。一旦您实现了这个模式,您将为您设计的数据结构获得最合理的内存使用
使用oConn作为新的SqlConnection(“Server=Myserv;Database=myDB;UserId=myuserid;Password=mypassword;”)
oConn.Open()
使用oCommand作为新的SqlCommand(“选择*来自用户”,oConn)
'其他需要的代码,请在使用…EndUsing中包装IDisposable
终端使用
终端使用
这并不能保证您的数据结构本身是内存高效的,只是它们只会在必要时保持资源
一,。是的,您有时不能使用using语句,但是如果您的前提是不使用using语句是错误的,那么您最好使用using语句。“为什么在函数中将某个东西设置为nothing与让它超出范围不同?”
您已经访问了somthing,因此在此之前它不符合GC的条件
当GC发生时有点不确定:显然,它会根据几个因素(引用:(视频))安排下一次调用。使用使用后必须释放的任何资源(包括DataTable或Dataset)的最佳方法是尽可能使用关键字using。如果无法使用Using关键字,则应执行与使用关键字等效的操作,如: 尝试 { } 捕获(例外情况除外) { } 最后 { object.dispose() } 根据msdn,任何实现IDisposable的对象都应该使用dispose方法释放资源 DataTable继承自实现IDisposable的MarshallByValueComponent,因此最好调用dispose方法。如果有 是任何未实现IDisposable方法的资源,则可以实现IDisposable接口并重写dispose 方法,并在dispose方法中执行资源清理。通过将DataSet或DataTable设置为null,您只需删除 最终将由垃圾收集器收集的引用。但使用dispose方法是更好的方法。你没有 显式调用GC.Collect方法,因为垃圾收集器通常在后台运行,并且只要内存 低于某个阈值(由编译器确定),它将释放这些资源所使用的内存。欲了解更多信息,请
请参阅垃圾收集()谢谢您的回复。在可能的情况下,我会将它们更改为使用这种“使用”模式。但在许多情况下,数据集或数据表是传递的,创建者不必承担处理任务。我的问题是关于传递的数据集和数据表的。对不起,我原来的问题不清楚。我将更新这个问题,但在包含以下循环的函数返回后,我将显式调用GC.Collect三次。对于i作为整数=0到50的oDA.Fill(ods)oDt=ods.Tables(0)'oDt.Clear()'oDt.Dispose()oDt=Nothing Next。因此,变量oDt在循环中被重用了50次。将新对象指定给变量后,这应该与将该变量设置为零一样好。但这里似乎不是这样,我不知道为什么。