【发布时间】:2015-04-30 10:51:11
【问题描述】:
这是我的代码:
using System;
using System.Collections.Generic;
using System.Threading;
namespace testt
{
class MainClass
{
public static List<TestObject> testjobs = new List<TestObject> ();
public static void Main (string[] args)
{
Console.WriteLine ("Hello World!");
addTask (); //put a breakpoint here
Thread.Sleep (5000);
deleteObj ();
while (true) {
Console.WriteLine ("MAIN STILL EXISTS!");
Thread.Sleep (1500);
GC.Collect ();
}
}
public static void addTask()
{
for (int i = 0; i < 10; i++)
{
testjobs.Add (new TestObject ());
testjobs [i].Start ();
}
}
public static void deleteObj()
{
for(int i=0; i<10;i++)
{
testjobs [0].dispose ();
testjobs.RemoveAt (0);
}
Console.WriteLine (testjobs.Count);
}
}
public class TestObject
{
private bool _isStopRequested;
private Thread _thread;
public void Start()
{
_thread = new Thread(ThreadRoutine);
_thread.Start();
}
public void Stop()
{
_isStopRequested = true;
if(!_thread.Join(5000))
{
_thread.Abort();
}
}
public void dispose(){
this.Stop ();
this._thread.Abort ();
this._thread=null;
}
private void ThreadRoutine()
{
//while(!_isStopRequested) //THIS CAUSES THE MEMORY LEAK!!!
{
Thread.Sleep (1);
}
Console.WriteLine ("THREAD FINISHED");
}
~TestObject(){
Console.WriteLine ("===================TESTOBJECT DESTROYED!!===============");
}
}
}
如果你在 //while(!_isStopRequested) 未注释的情况下运行它,TestObject 实例将不会被销毁,即不会调用它们的析构方法。
如果按原样运行,则只会销毁 4-8 个对象,而不是全部 10 个。
为什么当线程完全退出时会发生这种情况?我检查了 Xamarin 调试器,线程肯定已停止。如果您在 Xamarin 中的 addTask() 处放置断点;那么你可以看到那10个线程
对此我唯一的解释是线程以某种方式保留了对其父对象 TestObject 实例的引用,即使在它们完成后也是如此。当线程已经完成时,线程如何持有对其父对象的引用?
另外,如果我将Thread.Sleep(1) 更改为Thread.Sleep(5000),TestObjects 也将停止被收集。
另外,事实上,只有一些 TestObjects 被收集,而另一些则没有。
为什么会发生这些事情?如何确保在 deleteObj() 函数返回时所有的 TestObjects 都得到垃圾回收?
编辑:我刚刚在 Visual Studio (.NET) 中测试了完全相同的代码,并且所有对象都被垃圾收集,无论该行是否被注释掉。
因此,我现在认为这个问题是 Mono 特有的问题,并且从一开始就没有内存泄漏。
【问题讨论】:
标签: c# multithreading memory-leaks mono xamarin