考虑以下代码:
public class Class1
{
public static int c;
~Class1()
{
c++;
}
}
public class Class2
{
public static void Main()
{
{
var c1=new Class1();
//c1=null; // If this line is not commented out, at the Console.WriteLine call, it prints 1.
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Class1.c); // prints 0
Console.Read();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,即使main方法中的变量c1超出范围并且在GC.Collect()调用时没有被任何其他对象进一步引用,为什么它没有在那里完成?
根据我的经验,似乎大多数人会告诉你强制垃圾收集是不明智的,但在某些情况下,你正在使用大型对象,这些对象并不总是在0代收集,但内存是一个问题,是它可以强制收集?这样做有最好的做法吗?
如果这是一个显而易见的问题,我很抱歉,但谷歌或搜索都没有让我得到答案.
有没有办法完全删除数组?
我想相反的int[] array = new int[5]
按照这个SO答案,我正在做:
ThreadPool.QueueUserWorkItem(
delegate
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
});
Run Code Online (Sandbox Code Playgroud)
我的目标是在关闭一个包含大量图像/ PictureBox控件的大型WinForms表单后进行垃圾收集运行,以确保我的内存中不再有图像.(我确实相信我遵循Jon Skeet的指示).
我在后台线程中这样做是为了尝试让我的UI响应.
我的问题:
在后台线程中进行垃圾收集会给我带来什么好处吗?或者它实际上使我的应用程序更慢/挂起更长?
我有一个类Class,Thread它在它的构造函数中创建.该线程运行一个while(true)循环,从a读取非关键数据NetStream.线程将被析构函数中止:
~Class()
{
_thread.Abort();
_thread = null;
}
Run Code Online (Sandbox Code Playgroud)
当程序想要结束对Class实例 的使用时ClassInstance,它会调用:
ClassInstance = null;
GC.Collect;
Run Code Online (Sandbox Code Playgroud)
我认为这意味着那时候~Class()会自动调用 - 但事实并非如此.
该线程即使在Application.Exit()返回之后也会继续运行Main().
我的应用程序崩溃时出现内存不足的异常,有时可能还会因内存不足而导致其他异常.
我用这个简单的代码重现了这个问题:
for (int i = 0; i < 100000; i++)
var bmp = new RenderTargetBitmap(256, 256, 96, 96, PixelFormats.Default);
Run Code Online (Sandbox Code Playgroud)
理论上,这个代码不应该崩溃,因为位图应该自动被垃圾收集,但是当它以32位模式运行时它会一直崩溃.
问题可以修复如下:
for (int i = 0; i < 100000; i++)
{
var bmp = new RenderTargetBitmap(256, 256, 96, 96, PixelFormats.Default);
if (i % 500 == 0)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
Run Code Online (Sandbox Code Playgroud)
当然这个解决方案违背了你不应该明确地调用GC.Collect的常识,但我怀疑这是一个实际上有意义的场景.
任何人都可以提供任何明智的见解吗?有没有更好的方法来解决问题?
我们有一个WPF应用程序,基于Unity和MMVVVM模式.在应用程序生命周期中,可能存在多个项目生命周期,在每个项目生命周期之后,我们执行手动拆除并尝试释放ViewModel的所有引用.对于使用Unity的事件订阅,我们使用弱引用.因此我们假设在拆除之后,我们可以调用GC Collect,以便所有垃圾对象都被垃圾收集.我们还有另一个手动取消订阅所有事件的选项,但我们更喜欢垃圾收集,因为它将为我们清除大约200MB,这将有助于新项目加载.
有一个实例,我们观察到,如果我只调用GC.Collect一次,它的引用仍然会在内存中保留一段时间.
GC.Collect();
GC.WaitForPendingFinalizers();
Run Code Online (Sandbox Code Playgroud)
但如果我尝试连续两次调用GC,它会很好地清理所有内容.
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
Run Code Online (Sandbox Code Playgroud)
任何想法或指示将受到高度赞赏.
更新:
Class中没有定义Finalizer.
现在我也在考虑一个案例,其中这个对象在另一个可能有终结器的对象中被引用.在我们的框架中,我们只有DBProvider的终结器,所以我不认为,即使是这种情况.
可能重复:
何时可以调用GC.Collect?
据我所知,CLR为你做了所有这些垃圾收集,但是有理由手动调用GC.Collect()吗?
是否在关闭文件,处置图像资源或非托管资源时应该调用GC.Collect()以立即快速清理未使用的内存?
以下是我的程序的统计数据,它使用内存非常密集,在其峰值时消耗6 GB,但随后将所有内容保存到磁盘并留下很小的范围:

观察到几乎所有东西都超出了范围并被垃圾收集 - 堆大小很小.然而,.NET保持181 MB 承诺.
我不介意保留字节,因为它只占用地址空间.但是提交的内存很烦人 - 即使它只存在于页面文件中,它仍然相当多.