C#计时器无法滴答

12

我遇到了一个奇怪的问题... 过去几个小时一直让我烦恼不已... 我在Winform代码中插入的计时器(从工具栏中选择)不会触发...

我的程序中有几个窗体上的计时器,它们都能正常工作... 但当我尝试在另一个窗体上添加计时器时,就无法工作了... 我选中它,将其拖到窗体上,启用它,设置间隔并处理tick事件... 但什么都没有发生... 我甚至尝试在tick事件中放置像messagebox.show这样的随机代码,只是为了看看是否有任何反应,但什么都没有发生!!! 正如我所说,我的程序中还有其他窗体上的几个计时器,它们都能正常工作...

有什么建议吗?

先感谢您!


这是标准的Visual Studio生成的计时器代码...this.timer1 = new System.Windows.Forms.Timer(this.components); private System.Windows.Forms.Timer timer1; this.timer1.Enabled = true; this.timer1.Interval = 1000; this.timer1.Tick += new System.EventHandler(this.timer1_Tick_1); private void timer1_Tick_1(object sender, EventArgs e) { MessageBox.Show("计时器滴答声"); } - Andrej
您可以编辑原始帖子以添加代码。(有时评论会被隐藏) - Phil Gan
6个回答

13

我发现,如果我从非UI线程停止定时器,然后再次启动它,我会失去事件钩子。

我不知道“正确”的答案是什么,但对我来说这个方法效果很好:

public class BetterTimer : System.Windows.Forms.Timer
{
    public BetterTimer():base()        
    { base.Enabled = true; }

    public BetterTimer(System.ComponentModel.IContainer container) : base(container) 
    { base.Enabled = true; }

    private bool _Enabled;
    public override bool Enabled
    {
        get { return _Enabled; }
        set { _Enabled = value; }
    }

    protected override void OnTick(System.EventArgs e)
    { if (this.Enabled) base.OnTick(e); }
}

这种方法有三个要点:

1)通过重写构造函数,确保从一开始就启用基础计时器。

2)通过重写“Enabled”,我永远不让基础计时器被禁用,但是接口不会改变。

3)通过重写“OnTick”,我让覆盖的Enabled属性决定事件是否应该触发。

Start() 和 Stop() 通过分别将 Enabled 属性设置为 true 和 false 来工作。

顺便问一下 - 有人知道为什么当从非 UI 线程停止/禁用计时器时,事件从未触发(或被断开连接)吗?


3
这对我有用。显然,始终在UI线程上停止/启动System.Windows.Forms.Timer! - user1454265

7

不要在.enabled上启动System.Windows.Forms.Timer计时器...无论如何...我刚刚让它工作了...我将Visual Studio生成的代码从WINFORMNAME.designer.cs复制到WINFORMNAME.cs...我不知道为什么,但它可以工作...

System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Enabled = true;
timer.Interval = 1000; 
timer.Tick += new EventHandler(timer_Tick); 
        void timer_Tick(object sender, EventArgs e)
        {
//do something
        }

感谢大家的答案!

6

2
.Enabled=true 应该就足够了。 - H H
1
是的,这已经“足够”了。实际上,.Start() 就等同于将 enabled 设置为 True :) - Isak Savo
1
如果启用=true就足够了,并且它与调用.Start()相同,那么为什么它不起作用?他发布的VS生成代码是this.timer1.Enabled=true;。 - richard

3

回答你的最后一个问题,不允许操纵在另一个线程上创建的控件。您可以通过委托进行调用。


在一个无关的问题上,我不确定为什么我的.Show()或.ShowDialog()调用没有起作用。原来是因为我在跨线程调用。这个语句帮助我找到了问题所在。谢谢。 - Franklin_Skipdiddle
检查:TextBox.InvokeRequired,如果为真则调用解决了我的问题。 - Ali123

1
我以前遇到过这个问题。我是在设置间隔之前启用了计时器。交换这两行代码使其正常工作。

0

我遇到了和Andrej相同的问题,并且尝试了在网上找到的几个解决方案。

我的程序中每个表单都有时间限制(倒计时),以下是我的解决方法:

我采用了计算机工程解决方案。关掉它再重新打开!!:))我的意思是,我不知道为什么,但它有效!!

首先,我从.cs和设计文件中删除了所有计时器,然后在每个表单中添加了一个计时器,并为计时器和文本框设置了不同的名称,并逐一编写了相同的代码。

我只使用了timer.start()和Timer.stop()。

private void Form7_Load_1(object sender, EventArgs e)
    {
        timer7.Start();
    }

    int duration = 30;

    private void timer7_Tick(object sender, EventArgs e)
    {
        duration--;
        textBox7.Text = duration.ToString(); // to show the countdown 

        if (duration == 0)
        {
            timer7.Stop();
            MessageBox.Show("You ran out of time. Please go to the next page");

            this.Hide();
            Form8 f8 = new Form8();
            f8.ShowDialog();
        }
    }

希望对你有所帮助


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接