Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 数据集和内存泄漏_.net_Vb.net_Memory Management_Memory Leaks_Dataset - Fatal编程技术网

.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
    ,任务管理器中的最终内存消耗大约为30k

  • 如果我只是在循环内将变量设置为
    Nothing
    ,则最终内存约为15k。
    问题:为什么将变量设置为
    Nothing
    会产生影响

  • 如果我在循环中只调用
    Dispose
    方法,那么最终的内存大约是19k

  • 如果我只在循环中调用
    Clear
    ,那么最终的内存大约是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次。将新对象指定给变量后,这应该与将该变量设置为零一样好。但这里似乎不是这样,我不知道为什么。