Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 线程。计时器阻止GC收集_C# - Fatal编程技术网

C# 线程。计时器阻止GC收集

C# 线程。计时器阻止GC收集,c#,C#,我有一个内存泄漏问题,我想知道是否有人能告诉我我做错了什么(或者我错过了什么Microsoft bug)。下面是一个示例应用程序,演示了该问题。调用TestCollectTimer.Test()运行示例 问题是,无论创建了多少“MyTimerData”,或者调用了多少次GC.Collect(),MyTimerData的终结器在应用程序关闭之前都不会被调用 class TestCollectTimer { public static void Test() { f

我有一个内存泄漏问题,我想知道是否有人能告诉我我做错了什么(或者我错过了什么Microsoft bug)。下面是一个示例应用程序,演示了该问题。调用TestCollectTimer.Test()运行示例

问题是,无论创建了多少“MyTimerData”,或者调用了多少次GC.Collect(),MyTimerData的终结器在应用程序关闭之前都不会被调用

 class TestCollectTimer
{
    public static void Test()
    {
        for (int index_A = 0; index_A < 100000; index_A++)
        {
            MyTimerData mtd = new MyTimerData();
            mtd = null;
        }

        GC.Collect();
        Thread.Sleep(2000);
        GC.Collect();

        Form f = new Form();
        f.ShowDialog();
    }
}

class MyTimerData
{
    public System.Threading.Timer m_timer;

    public MyTimerData()
    {
        this.m_timer = new System.Threading.Timer(
            new System.Threading.TimerCallback(this.TimerCall),
            null,
            System.Threading.Timeout.Infinite,
            System.Threading.Timeout.Infinite);
    }

    ~MyTimerData()
    {
        MessageBox.Show("Collect My Timer Data");
    }

    public void TimerCall(object o) { }
}
类TestCollectTimer
{
公共静态无效测试()
{
对于(int index_A=0;index_A<100000;index_A++)
{
MyTimerData mtd=新MyTimerData();
mtd=null;
}
GC.Collect();
《睡眠》(2000年);
GC.Collect();
表格f=新表格();
f、 ShowDialog();
}
}
类MyTimerData
{
公共系统.Threading.Timer m_Timer;
公共MyTimerData()
{
this.m_timer=new System.Threading.timer(
新系统.Threading.TimerCallback(this.TimerCall),
无效的
System.Threading.Timeout.Infinite,
系统、线程、超时、无限);
}
~MyTimerData()
{
Show(“收集我的计时器数据”);
}
公共无效TimerCall(对象o){}
}

感谢您的帮助

在调试模式下,所有局部变量的作用域都被人为地扩展到其封闭方法的末尾,因此在您在调试器中完成检查之前不会收集它们

当在发布模式下编译并在没有附加调试程序的情况下运行时,您的代码可以正常工作


您也可以将for循环移动到它自己的方法中,这样,即使在调试模式下,计时器也可以在返回后进行收集。

如何处理计时器

class TestCollectTimer
{
    public static void Test()
    {
    for (int index_A = 0; index_A < 100000; index_A++)
    {
        using(MyTimerData mtd = new MyTimerData())
        {
           //do your stuff here
        }

    }

    GC.Collect();

    Form f = new Form();
    f.ShowDialog();
}
}

class MyTimerData : IDisposable
{
public System.Threading.Timer m_timer;

public MyTimerData()
{
    this.m_timer = new System.Threading.Timer(
        new System.Threading.TimerCallback(this.TimerCall),
        null,
        System.Threading.Timeout.Infinite,
        System.Threading.Timeout.Infinite);
}

public void TimerCall(object o) { }

public void Dispose()
{
    Dispose(true);
}

protected void Dispose(bool disposing)
{
   m_timer.Dispose();
   GC.SuppressFinalize(this);
}
}
类TestCollectTimer
{
公共静态无效测试()
{
对于(int index_A=0;index_A<100000;index_A++)
{
使用(MyTimerData mtd=new MyTimerData())
{
//在这里做你的事
}
}
GC.Collect();
表格f=新表格();
f、 ShowDialog();
}
}
类MyTimerData:IDisposable
{
公共系统.Threading.Timer m_Timer;
公共MyTimerData()
{
this.m_timer=new System.Threading.timer(
新系统.Threading.TimerCallback(this.TimerCall),
无效的
System.Threading.Timeout.Infinite,
系统、线程、超时、无限);
}
公共无效TimerCall(对象o){}
公共空间处置()
{
处置(真实);
}
受保护的无效处置(bool处置)
{
m_timer.Dispose();
总干事(本);
}
}

您可以查看规则CA1001:

在发布模式下运行它,而不附加调试程序。看,我想这是因为你启动了计时器,但没有停止。运行计时器可以让自己保持活力,这样他们就不会被垃圾收集(因为这比你的计时器无法预知地死去要好)。我不确定通过传递Timeout.Infinite这两个参数来完成什么任务。不过,你说的是“创建一个永远不会启动的计时器”。@joewite这与:“只要使用计时器,就必须保留对它的引用。与任何托管对象一样,当没有对计时器的引用时,计时器将接受垃圾收集。计时器仍处于活动状态这一事实并不妨碍对其进行收集。”