FormClosing后的计时器滴答?

时间:2012-08-14 17:18:33

标签: c# winforms

在myForm_FormClosing之后是否有任何机会可以调用timer_Tick 在下面的代码中。

如果有机会:在myForm_FormClosing中调用timer.Stop()是否足以避免在myForm_FormClosing之后调用timer_Tick?

using System;
using System.Windows.Forms;
using System.ComponentModel;

namespace Test
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MyForm());
        }
    }

    class MyForm : Form
    {
        private IContainer components;
        private Timer timer;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        public MyForm()
        {
            components = new Container();
            timer = new Timer(components);

            timer.Interval = 50;
            timer.Tick += timer_Tick;
            timer.Enabled = true;

            FormClosing += myForm_FormClosing;
        }

        private void timer_Tick(object sender, EventArgs e)
        {
        }

        private void myForm_FormClosing(object sender, FormClosingEventArgs e)
        {
        }
    }
}

更新: 在收到一些提示后(感谢您的帮助)我基本上选择了以下代码来实现我想要的。 请注意,调用myForm_FormClosing后仍然可以调用timer1_Tick! 这个解决方案只是引入了一个标志(我称之为doWork),它会在调用myForm_FormClosing之后停止timer1_Tick中的代码。

using System;
using System.Windows.Forms;
using System.ComponentModel;

namespace Test
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MyForm());
        }
    }

    class MyForm : Form
    {
        private IContainer components;
        private Timer timer;
        private bool  doWork = true;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        public MyForm()
        {
            components = new Container();
            timer = new Timer(components);

            timer.Interval = 50;
            timer.Tick += timer_Tick;
            timer.Enabled = true;

            FormClosing += myForm_FormClosing;
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            if (doWork)
            {
                //do the work
            }
        }

        private void myForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            doWork = false;
        }
    }
}

3 个答案:

答案 0 :(得分:2)

是的,这是可能的。根据{{​​3}} ...

  

在表单关闭之前发生。

     

当表单关闭时,它会被释放,释放所有资源   与表格相关联。

在FormClosing事件发生之前,计时器不会被释放。这是一个非常人为的示例,说明它是如何发生的。调用FormClosing后,您将看到在Timer定时器上打到调试器断点。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private System.Windows.Forms.Timer _time = new System.Windows.Forms.Timer();
        private Task _t1 = null;
        private Task _t2 = null;
        private bool _closingFlag = false;
        public Form1()
        {
            InitializeComponent();

            _time.Interval = 50;
            _time.Tick += (s, e) => { 
                textBox1.Text = DateTime.Now.ToString();
                if (_closingFlag) Debugger.Break();
            };

            _time.Start();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _closingFlag = true;

            _t1 = Task.Factory.StartNew(() => { Thread.Sleep(1000); });
            _t2 = Task.Factory.StartNew(() => { Thread.Sleep(1000); });

            Task.WaitAll(_t1, _t2);
        }
    }
}

答案 1 :(得分:1)

如果您使用计时器System.Windows.Forms.Timer,则UI线程必须处于空闲状态才能处理来自计时器的勾号,因此根据我的理解,这是不可能的。

如果您使用具有自己的线程的计时器,可能会发生System.Timers.Timer。在这种情况下,我们可以通过实现以下内容来避免您提到的内容:

class MyForm : Form
{
    private System.Timers.Timer timer;

    private Object justForLocking = new Object();
    private Boolean safeToProceed = true;

    [...]

    public MyForm()
    {
        components = new Container();
        timer = new System.Timers.Timer();

        timer.Interval = 50;
        timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        timer.Start();

        FormClosing += myForm_FormClosing;
    }

    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
         // In case that this code is being executed after
         // the method myForm_FormClosing has adquired the 
         // exclusive lock over our dummy resource,
         // the timer thread will wait until the resource if released.
         // Once is released, our control flag will be set to false
         // and the timer should just return and never execute again.
         lock(justForLocking)
         {
             if (safeToProceed)
             {
                 // Do whatever you want to do at this point
             }
         }
    }

    private void myForm_FormClosing(object sender, FormClosingEventArgs e)
    {
         lock(justForLocking)
         {
             safeToProceed = false;
         }
         timer.Stop();

         // Do something else
    }

    [...]
}

此其他SO question有相关信息。

编辑:上述代码仅在使用System.Timers.Timer而非System.Windows.Forms.Timer

时才有效

答案 2 :(得分:0)

我不相信,但无论如何最好调用timer.stop()。如果你需要它,虽然你应该在program.cs中创建计时器对象

相关问题