如何销毁 List Of(T),重新分配列表使用的内存
Posted
技术标签:
【中文标题】如何销毁 List Of(T),重新分配列表使用的内存【英文标题】:How to destroy a List Of(T), reallocate memory used by the list 【发布时间】:2013-07-21 13:34:25 【问题描述】:VB.NET 2010,框架 3.5
在完成自定义对象类型列表后,试图弄清楚如何取回内存。我知道强制列表超出范围会重新分配它正在使用的内存,但我需要一种务实的方法。有谁知道怎么做?
Public Class List_Of_T_Test
Private MyTestClass As New List(Of TestClass)
Private Sub List_Of_T_Test_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Const LIST_COUNT As Integer = 5000000
Dim Count As Integer = 0
MsgBox("Note 'PF usage' on Windows Task Manager 'before the 5m list' is created")
Do Until Count > LIST_COUNT ' 5 million iterations
MyTestClass.Add(New TestClass With .Value1 = CStr(Count), .Value2 = CStr(Count + 1))
Count = Count + 1
Loop
MsgBox("Note 'PF usage' on Windows Task Manager 'after the 5m list' was created")
DestroyMyTestClassList()
MsgBox("When flow arrives here, I need MyTestClass to be gone, all memory to have been reallocated, or close to where it was before the list was created")
End Sub
Private Sub DestroyMyTestClassList()
' Does anyone know what code to put here, code that would totally destroy
' the MyTestClass and the 5 million items in it, reallocate the memory used
' by the list Of(T) MyTestClass
' MyTestClass.Clear() ' Doesn't work ??
' MyTestClass = Nothing ' Doesn't work ?
End Sub
Public Class TestClass
Public Property Value1 As String
Public Property Value2 As String
End Class
End Class
我理解让它超出范围的想法,但我必须告诉你,我尝试处理表单、关闭它等并加载单独的表单,但内存仍然没有恢复。我猜 GC 还没有搞定它的收集业务之类的。我猜我得再看 GC 的工作时间了
这个名叫 Jods 的家伙很好奇我为什么要以编程方式执行此操作。我正在做的工作类型,创建大量类型的自定义列表,这些列表本质上是非常动态的,我需要一种方法来销毁它们并重建它们,确保旧的东西已经消失了。这些应用程序有时会连续运行数周。 .我需要密切注意记忆等等。
如果有人感兴趣,请参阅下面的代码,该代码似乎从对象列表中重新分配内存
Public Class List_Of_T_Test
Private MyTestClass As New List(Of TestClass)
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Const LIST_COUNT As Integer = 5000000
Dim Count As Integer = 1
Do Until Count > LIST_COUNT ' 5 million iterations
MyTestClass.Add(New TestClass With .Value1 = CStr(Count), .Value2 = CStr(Count + 1))
Count = Count + 1
Loop
MsgBox(MyTestClass.Count.ToString)
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
' This seems to completely reallocate the memory, paste this into a form's code,
' add two buttons, click button1 once, or few times while watching the
' 'Windows Task Manager' PF Usage.
' Then Click button2 once and the memory spike levels off, it all comes back
MyTestClass = New List(Of TestClass)
GC.Collect() ' ?
End Sub
Private Class TestClass
Public Property Value1 As String
Public Property Value2 As String
End Class
End Class
【问题讨论】:
只需将其设为方法的局部变量,而不是类成员。 Windows 和垃圾收集器都没有您正在寻找的行为,在不需要时故意释放资源太昂贵了。 从昨天开始我就一直在努力解决这个问题。这两行似乎工作得很好,内存似乎立即重新分配。 'MyTestClass = New List(Of TestClass)' 和 'GC.Collect()' 你或其他人认为这种方法有问题吗? 【参考方案1】:我很好奇为什么您需要一种以编程方式执行此操作的方法。当您的对象不再使用时(所有引用都无法访问/超出范围/或设置为 null),内存将由垃圾收集器的下一次运行回收。
如果你想通过代码触发一个集合,你应该调用 GC.Collect()。如果你有终结器,你可能需要调用 GC.WaitForPendingFinalizers() 然后 GC.Collect() 再次。
请注意,调用这些方法通常是不受欢迎的,所以我对你的情况很好奇。
【讨论】:
还要注意 GC.Collect() 是一个请求,并不保证会执行。 msdn.microsoft.com/en-us/library/xe0c2357.aspx @ginman 我记得曾经讨论过这个问题,但细节一直没让我知道。我记得这更多是理论上的考虑,而不是实际的考虑。顺便说一句,您的 MSDN 链接说:“强制所有代立即进行垃圾收集。”没有提及可能不执行 GC。 是的,这是误导。进一步说明:“使用此方法尝试回收所有无法访问的内存。”它的作用是强制 GC 收集线程运行,这并不能保证收集。请参阅 GC.Collect 未按预期回收内存的此问题 - ***.com/questions/888280/…【参考方案2】:当 .NET 框架实例化一个对象时,它会在托管堆上为该对象分配内存。该对象保留在堆上,直到它不再被任何活动代码引用,此时它使用的内存是“垃圾”,准备好由 .NET 垃圾收集器 (GC) 进行内存释放。在 GC 释放内存之前,框架会调用对象的 Finalize() 方法,但开发人员负责调用 Dispose() 方法。
所以,只需调用对象的 Dispose() 方法即可。
【讨论】:
这毫无意义。 Dispose 与内存没有任何关系,List 类也没有实现它。 Dispose 用于释放非托管资源。如果列表没有任何对其的引用,它将由垃圾收集器在适当的时候释放。以上是关于如何销毁 List Of(T),重新分配列表使用的内存的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin 协程:从 Flow<sealed class <list of <T>>> 中获取 (T) 列表
C#如何把List of Object转换成List of T具体类型
如何创建一个 List(of T),其中 T 是 (T) 的接口,并且 List 的内容继承了实现 T 接口的 Abstract 类