C# - Winforms - 在计时器的帮助下重复方法

时间:2017-05-26 19:35:40

标签: c# winforms timer

我最近开始学习C#,我试图在计时器的帮助下每分钟重复一次方法。该方法更改标签的值。但是,我收到以下错误:

  

$ exception {“跨线程操作无效:控制'label1'   从创建它的线程以外的线程访问   on。“} System.Exception {System.InvalidOperationException}

我试过寻找解决方案,每个线程都让我感到困惑。我不仅需要正确的代码,还需要解释,因为我想学习在定时器和线程的帮助下操作UI。

以下是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Timers;
using System.Windows.Forms;



namespace Winforms_Timer_and_Thread
{
    public partial class Form1 : Form
    {

        System.Timers.Timer myTimer = new System.Timers.Timer();
        public Form1()
        {
            myTimer.Enabled = true;
            InitializeComponent();
        }

        public void startMethod(object senter, ElapsedEventArgs e)
        {
            int cntr = 0;
            cntr++;
            label1.Text = "Executed: " + cntr.ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = "Started!";
            myTimer.Enabled = true;
            myTimer.Interval=(1*60*1000);
            myTimer.Elapsed += new System.Timers.ElapsedEventHandler(startMethod);

        }

    }
}

1 个答案:

答案 0 :(得分:2)

如果您更改为使用System.Windows.Forms.Timer,则您不会遇到此问题,因为它在同一个UI线程中执行。

您只需要更改:

  • System.Timers.TimerSystem.Windows.Forms.Timer
  • 的计时器类型
  • Elapsed订阅到Tick
  • 的活动
  • 事件签名,其中ElapsedEventArgs e变为EventArgs e

您也只需要订阅一次事件,而不是每次都启用计时器,因此请将其移至Form_Load事件以及Interval分配(尽管可以更改)任何时候)。

您也可能希望将计数器变量存储在StartMethod之外,因此每次执行时它都会递增,然后在每次启动计时器时将其重置为零:

public partial class Form1 : Form
{
    readonly System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
    private int tickCounter;

    public Form1()
    {
        InitializeComponent();

        myTimer.Interval = (int)TimeSpan.FromMinutes(1).TotalMilliseconds;
        myTimer.Tick += StartMethod;
    }

    private void StartMethod(object sender, EventArgs e)
    {
        tickCounter++;
        label1.Text = "Number of executions: " + tickCounter;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        tickCounter = 0;
        label1.Text = "Started!";
        myTimer.Enabled = true;
    }
}