WP8 - GC.Collect()不起作用

时间:2014-07-23 08:17:40

标签: c# windows-phone-8 memory-leaks garbage-collection

我有一些内存泄漏的麻烦。 这是我的测试代码:

// 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

那么,为什么“wr”在调用GC.Collect()后仍然存活? GC出了什么问题? 我在WP8& WP8.1预览。 你能帮帮我吗?

3 个答案:

答案 0 :(得分:2)

你有一个字符串的引用,因为它是一个常量,可能是实习的,永远不会被收集:

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");

答案 1 :(得分:1)

也许是因为字符串文字存储在internal dictionary中以防止重复?有关详细信息,请参阅此处:String interning and String.Empty

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

答案 2 :(得分:0)

你永远不应该依赖GC.Collect()来回收记忆。 .NET是一个托管环境,您可以将内存管理控制权交给运行时,以换取不必编写直接管理它的代码,并带来所有考虑因素。

调用GC.Collect()只是告诉运行时它可能希望在下一次获得机会时运行一个收集周期 - 它不会中止一些复杂的计算,它只是在做垃圾的过程中集合。

即使这样,集合也只会发生在任何代码都无法访问的对象上,然后垃圾收集器中有三层缓存,因此在调用GC.Collect()时期望对象立即消失错误的做事方式。

正确构建程序不需要依赖GC.Collect()。如果实例只在需要的地方可用,那么程序的其他区域就不会出现问题。最后,如果wr对象被垃圾回收,您拨打.IsAlive()会产生未处理的NullReferenceException