C# 窗体关闭后计时器滴答作响?

C# 窗体关闭后计时器滴答作响?,c#,winforms,C#,Winforms,在myForm关闭后是否有可能调用timer_Tick 在下面的代码中 如果有机会:在myForm\u FormClosing中调用timer.Stop()是否足以避免在myForm\u FormClosing之后调用timer\u Tick using System; using System.Windows.Forms; using System.ComponentModel; namespace Test { static class Program {

在myForm关闭后是否有可能调用timer_Tick 在下面的代码中

如果有机会:在myForm\u FormClosing中调用timer.Stop()是否足以避免在myForm\u FormClosing之后调用timer\u 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\u FormClosing后仍然调用timer1\u Tick! 这个解决方案只是引入了一个标志(我称之为doWork),它在调用myForm\u FormClosing后要执行的计时器1_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;
        }
    }
}

我不这么认为,但无论如何最好还是调用timer.stop()不管怎样。如果您需要它,您应该在program.cs中创建计时器对象,这是可能的。根据

在窗体关闭之前发生

当表单关闭时,它将被释放,释放所有资源 与表单关联

只有在FormClosing事件之后,才会释放计时器。下面是一个非常做作的例子,说明了它是如何发生的。在调用FormClosing后,您将看到在计时器刻度上点击调试器断点

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

如果使用计时器
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
    }

    [...]
}
另一个有相关信息


编辑:仅当使用
System.Timers.Timer
而不是System.Windows.Forms.Timer

是和是时,上述代码才有效。如果myForm_FormClosing将是一个紧张的过程,请确保提前停止计时器。此外,如果取消关闭,请确保在必要时重新启动计时器。@PowerRoy是的,我已经尝试过了。在myForm关闭后,没有调用timer_Tick。但这并不能保证不会有这样的机会。@J-托雷斯谢谢你的回答。但是你能解释一下为什么答案是肯定的和肯定的吗。有没有关于这方面的文件。(我没有发现任何特殊情况。)OP,@JPAlioto提供了一个很好的例子来说明这是如何发生的。@JTorres感谢您指出这一点。请注意,
Stop()
不能保证tick现在没有调用回调。我不想在Main方法中创建计时器(我猜你所说的program.cs就是这个意思)但在Form1中,您可以使用bools解决一些问题,以确保tick的功能只能在特定时间发生。我认为您不需要使用锁,我认为计时器与其余代码共享一个线程。@user1580785请看顶部的更新部分。我想这就是您的意思。为什么需要同步当这两个方法在同一个线程中被调用时?你是对的。我混合了一些对其他类型计时器有效的代码。我将编辑post.Mmmh…似乎如果我调用_time.Stop()在Form1\u FormClosing的结尾处,勾号方法没有上升。有人能确认吗?@thiel无论你做什么,这仍然是一个竞争条件。如果你必须让并发完成,你需要用正常的多线程方法来处理。好的。我想我只是在Form1\u FormClosing中设置了一个标记,并用在Tick EventHandler中,以避免执行我不想执行的事情。你们对此有何看法?我不认为在
System.Windows.Forms.Timer
@LuisQuijada中会发生这种情况。抱歉,我不明白你们的意思。