计时器每秒触发一次并更新 GUI(C# Windows 窗体)

Posted

技术标签:

【中文标题】计时器每秒触发一次并更新 GUI(C# Windows 窗体)【英文标题】:Timer firing every second and updating GUI (C# Windows Forms) 【发布时间】:2020-02-14 19:43:27 【问题描述】:

我有一个 Windows 窗体应用程序,我需要一个计时器工作 90 秒,并且在它过去后每一秒都应该显示,有点像秒表 1..2..3 等,在 90 秒结束后,它应该抛出异常,表明有问题。

我有以下代码,但 RunEvent 永远不会触发。

        private void ScanpXRF()
        
            bool demo = false;

            System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

            try
            

                for (int timerCounter = 0; timerCounter < 90; timerCounter++)
                
                    timer.Interval = 1000;
                    timer.Tick += new EventHandler(RunEvent);
                    timer.Start();

                    if(timerCounter == 89) 
                      throw new Exception(); 
                     
                

            
            catch (Exception e)
            
                timer.Dispose();
                MessageBox.Show("There is a problem!");                   
                   
        


          private void RunEvent(object sender, System.EventArgs e)
            
                //boxStatus.AppendText("RunEvent() called at " + DateTime.Now.ToLongTimeString() + "\n");
                MessageBox.Show("timer fired!");
            

我在这里做错了什么还是有其他建议可以通过其他方式达到相同的结果?

【问题讨论】:

你没有打电话给ScanpXRF()。如果你这样做了,你会看到立即抛出异常。 是的,我正在调用它。我有断点,这不是问题。 哇,等一下...我可能读错了,但是为什么你要循环 91 次并重新设置间隔,甚至(再次)订阅 Tick,然后再次调用 Start ?我不经常使用计时器,但这对我来说真的很奇怪。 但是你应该打这个:throw new Exception() 非常快。您的代码中没有任何内容可以阻止它到达那里。你使用的那个循环搞砸了。 我的评论被删除了 我的也是。指出 MessageBox 在这里不是一个很好的帮助是一个有用的提示 imo。我想知道是谁和为什么这样做的? CoC涟漪?我在黑名单上吗? 【参考方案1】:

定时器需要在表单级别声明,否则表单关闭时可能不会被销毁:

System.Windows.Forms.Timer timer;
int counter = 0;

您的启动代码应该只是启动计时器:

private void ScanpXRF()

   counter = 0;
   timer = new System.Windows.Forms.Timer();
   timer.Interval = 1000;
   timer.Tick += RunEvent;
   timer.Start();

RunEvent 是你的 Tick 事件每秒被调用一次,所以你的逻辑需要进去:

private void RunEvent(object sender, EventArgs e)

  counter++;
  if (counter >= 90) 
    timer.Stop();
    // do something...
  

【讨论】:

需要在表单级别声明计时器 - 你能从文档中备份吗? 我的问题是 Tick 事件没有触发......我在设计器表单中声明了计时器并在那里设置了属性。 @sarsnake 那是因为它正在被垃圾收集。您需要保留对计时器的引用;因此在表单级别声明它。 好的,但仍然可以自己处理。它如何解释 OPs 问题?答案当然显示了如何使整体逻辑正确,但 OP 代码仍应达到RunEvent,对吧? @sarsnake 不,计时器会根据您的时间间隔引发该滴答事件。间隔 1000 将每秒调用 Tick 事件。您将 Tick 事件映射到 RunEvent 方法,因此 RunEvent 将每秒运行一次。这就是为什么在我的代码中,当计数器为 90 或更大时,我调用 Stop(),这将使计时器停止调用 RunEvent。【参考方案2】:

成功了

   private void ScanpXRF()
        
            _pXRFTimerCounter = 0;
            pXRFTimer.Enabled = true;
            pXRFTimer.Interval = 1000;
            pXRFTimer.Elapsed += new ElapsedEventHandler(pXRFTimer_Tick);
            pXRFTimer.Start();
        

        private static void pXRFTimer_Tick(Object sender, EventArgs e)
        
            _pXRFTimerCounter++;

            if (_pXRFTimerCounter >= 90)
            
                pXRFTimer.Stop();
                // do something...               
            
            else
            
                MessageBox.Show(_pXRFTimerCounter.ToString() + " seconds passed");
            
        

我做了计时器

系统定时器

【讨论】:

以上是关于计时器每秒触发一次并更新 GUI(C# Windows 窗体)的主要内容,如果未能解决你的问题,请参考以下文章

React:ClearInterval 并立即重新开始

Android listview 计时器每秒运行一次

计算从现在到明年的倒计时(包含天,时,分,秒),每秒更新一次

CreateJS不会在动画中每秒更新一次动态文本框HTML 5 Canvas

捕获倒计时或滴答事件 - Threading.Timer C#

Swift:当定时器触发时,如何阻止平移手势取消?