C# 防止这种不安全的交叉线程

C# 防止这种不安全的交叉线程,c#,multithreading,C#,Multithreading,我有以下代码: private void Form1_Load(object sender, EventArgs e) { /*start update timer*/ System.Timers.Timer updateticker = new System.Timers.Timer(); updateticker.Elapsed += new ElapsedEventHandler(update_ove

我有以下代码:

 private void Form1_Load(object sender, EventArgs e)
        {
            /*start update timer*/
            System.Timers.Timer updateticker = new System.Timers.Timer();
            updateticker.Elapsed += new ElapsedEventHandler(update_overload);
            //10 minute ticker
            updateticker.Interval = 600000;
            //30 sec ticker
            updateticker.Interval = 30000;
            updateticker.Enabled = true;

            System.Timers.Timer guiTimer = new System.Timers.Timer();
            guiTimer.Elapsed += new ElapsedEventHandler(idle_display);
            //1 minute ticker
            guiTimer.Interval = 60000;
            //30 sec ticker
            //updateticker.Interval = 30000;
            guiTimer.Enabled = true;

        }

 //run front end idle timer
        public void idle_display(object source, ElapsedEventArgs e)
        {
            if (minutes_left > 0) {
                minutes_left = minutes_left - 1;
            }

            lbl_dyn_status.Text = "Time until next automatic update: "+ minutes_left + " minutes.";
        }
Visual studio将第二个函数的最后一行标记为不安全的跨线程。有人能建议我如何重写这个来解决这个问题吗


干杯

使用
System.Windows.Forms.Timer
而不是
System.Timers.Timer

或使用计时器的属性

当SynchronizingObject为null时,将对系统线程池中的线程调用处理已用事件的方法。有关系统线程池的更多信息,请参阅线程池

当由可视Windows窗体组件(如按钮)处理已用事件时,通过系统线程池访问该组件可能会导致异常或无法工作。通过将SynchronizingObject设置为Windows窗体组件来避免此影响,这会导致在创建组件的同一线程上调用处理已用事件的方法


使用System.Windows.Forms.Timer Timer而不是System.Timers.Timer。

如其他人所建议的,使用。与在线程池线程上操作不同,它保证在UI线程上调用tick事件

UI线程是唯一允许修改UI的线程。这就是为什么尝试写入
lbl\u dyn\u状态时会出现异常。Text

将处理程序更改为

public void IdleDisplay(object source, ElapsedEventArgs e)
{
    if (lbl_dyn_status.InvokeRequired)
    {
        this.Invoke(IdleDisplay)
    }
    else
    {
        if (minutes_left > 0)
        {
            minutes_left = minutes_left - 1;
        }

        lbl_dyn_status.Text = string.Format(
            "Time until next automatic update: {0} minutes.",
             minutes_left);
    }
}
这种方式允许您使用无线程的
System.Threading.Timer
,但会检查处理程序中的跨线程调用。如果检测到调用,则通过
表单
类在主GUI线程上调用

这是描述的


更一般地说,您不应该像这样使用计时器来计算时间。计时器的线程绑定越多,就越有可能偏离实际运行时间。您可以使用计时器计划时钟的更新,但是,您应该计算从某个固定点开始经过的时间,而不是使用迭代计数器。

system.timers.timer如果不能与用户交互,它的用途是什么?它对任何没有用户交互的情况都很有用,例如,在windows服务中定期运行操作。正如我在回答中所述,像这样迭代地计算时间是个坏主意。