【问题标题】:Garbage Collection - is it required?垃圾收集 - 是否需要?
【发布时间】:2012-04-18 07:19:33
【问题描述】:

一般来说,垃圾收集是一种很好的做法,因为它可以释放资源。 如何在以下代码的keepingTime 方法中实现正确的垃圾回收?或者,事实上,我什至需要?!

System.Timers.Timer 允许 IDisposable 接口,因此“使用”是一个选项,但在以下情况下不可以,因为计时器的范围需要扩展到订阅 Timer Elapsed 事件的方法 myTimer_Elapsed。我已经进行了两次垃圾收集尝试,但都失败了,因为计时器没有停留足够长的时间!

我之前在HERE

中讨论过此代码,出于其他原因
public partial class AirportParking : Form
{

    //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    //instance variables of the form
    System.Timers.Timer myTimer;

    private const string EvenText = "hello";
    private const string OddText = "hello world";

    static int tickLength = 100; 
    static int elapsedCounter;
    private int MaxTime = 5000;
    private TimeSpan elapsedTime; 
    private readonly DateTime startTime = DateTime.Now; 
    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


    public AirportParking()
    {
        InitializeComponent();
        lblValue.Text = EvenText;
        keepingTime();
    }

    //method for keeping time
    public void keepingTime() {

        myTimer = new System.Timers.Timer(tickLength);
        myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
        myTimer.AutoReset = true;
        myTimer.Enabled = true;
        myTimer.Start();

        //ATTEMPT_1.tried the following unsuccessfully
        //using (System.Timers.Timer myTimer = new System.Timers.Timer(tickLength))
        //{
        //    myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
        //    myTimer.AutoReset = true;
        //    myTimer.Enabled = true;
        //    myTimer.Start();
        //}

        //ATTEMPT_2.tried the following unsuccessfully
        //myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
        //myTimer.AutoReset = true;
        //myTimer.Enabled = true;           
        //try
        //{
        //    myTimer.Start();
        //}
        //finally
        //{
        //    myTimer.Dispose();
        //}

    }

    private void myTimer_Elapsed(Object myObject,EventArgs myEventArgs){

        elapsedCounter++;
        elapsedTime = DateTime.Now.Subtract(startTime);

        if (elapsedTime.TotalMilliseconds < MaxTime)
        {
            this.BeginInvoke(new MethodInvoker(delegate
            {
                this.lblElapsedTime.Text = elapsedTime.ToString();

                if (elapsedCounter % 2 == 0)
                    this.lblValue.Text = EvenText;
                else
                    this.lblValue.Text = OddText;
            }));
        }
        else {myTimer.Stop();}
    }
}

【问题讨论】:

  • 而且你描述的不是垃圾收藏。 IDisposable 与 GC 无关。

标签: c# winforms garbage-collection


【解决方案1】:

您要释放计时器资源的唯一位置是回调函数myTimer_Elapsed。在你做myTime.Stop();的地方你也可以做myTimer.Dispose();

但是,当应用程序的这一部分超出范围时,所有这些变量都会被清除。只要计时器最终停止,一旦它被取消引用,它就会被 GC 收集。

using 块(以及您当前的Dispose())不起作用的原因是您在创建计时器后就将其丢弃!你必须让它在后台运行。

【讨论】:

    【解决方案2】:

    在 Form 的 OnClosing 事件上设置你的计时器,如果这不是一个主表单,或者顺便说一下,一个始终可见的表单。

    伪代码可能如下所示:

    public partial class AirportParking : Form
    {
      .....
      .....
    
      protected override void OnClosing(...)
      {
           myTimer.Dispose();
      }
    }
    

    如果这是一些“长期运行”的表单,你应该在不再需要它的时候添加对 timere 的处理,但我想你已经知道了。

    【讨论】:

      【解决方案3】:

      虽然垃圾收集是一种很好的做法,但在这种情况下,它会在您关闭表单或实例死亡时自动完成。

      我真正担心这一点的唯一一次是 SQL 阅读器,因为您必须确保在完成后关闭它们,否则会导致各种问题。

      【讨论】:

        猜你喜欢
        • 2012-04-14
        • 1970-01-01
        • 2013-03-09
        • 2011-10-12
        • 1970-01-01
        • 2011-01-26
        • 2021-05-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多