WP8 - GC.Collect() don't work

本文关键字:work don GC Collect WP8 | 更新日期: 2023-09-27 18:14:24

我有一些内存泄漏的问题。下面是我的测试代码:

// Create the object
string book = "This is a book";
Debug.WriteLine(book);
// Set weak reference
WeakReference wr = new WeakReference(book);
// Remove any reference to the book by making it null
book = null;
if (wr.IsAlive)
{
     Debug.WriteLine("Book is alive");
     var book2 = wr.Target as string;
     Debug.WriteLine("again -> " + book2);
     book2 = null;
}
else
     Debug.WriteLine("Book is dead");
// Lets see what happens after GC
GC.Collect();
GC.WaitForPendingFinalizers();
// Should not be alive
if (wr.IsAlive)
    Debug.WriteLine("again -> Book is alive");
else
    Debug.WriteLine("again -> Book is dead");

输出为:

This is a book
Book is alive
again -> This is a book
again -> Book is alive

那么,为什么在调用GC.Collect()之后"wr"仍然活着?GC有什么问题吗?我在WP8上运行。WP8.1预览。

WP8 - GC.Collect() don't work

您有一个对字符串的引用,由于它是常量,因此可能被拘禁并且永远不会被收集:

string strBook = wr.Target as string;
if(strBook  != null) {
    Console.WriteLine("again -> Book is alive");
    if(string.IsInterned(strBook) != null)
        Debug.WriteLine("Because this string is interned");
}
else Console.WriteLine("again -> Book is dead");

也许是因为字符串字面值存储在内部字典中以防止重复?查看这里的详细信息:字符串实习和字符串。空

尝试分配一个POCO类(例如StringBuilder),而不是一个字符串文字为您的测试。

你永远不应该依赖GC.Collect()来回收内存。. net是一个托管环境,你把内存管理的控制权交给运行时,以换取不必编写直接管理它的代码,以及由此带来的所有考虑。

调用GC.Collect()只是告诉运行时,它可能希望在下一次有机会的时候运行一个收集周期——它不会为了做一个垃圾收集而中止一些正在进行的复杂计算。

即使这样,收集也只会发生在那些不再被任何代码访问的对象上,然后在垃圾收集器中有三层缓存,所以期望当GC.Collect()被调用时对象立即消失是错误的。

正确构建您的程序应该消除依赖GC.Collect()的需要。如果实例只在需要的地方可用,那么程序的其他部分就不会干扰它们。最后,如果wr对象被垃圾收集,那么对.IsAlive()的调用将产生一个未处理的NullReferenceException