0

我有这个代码:

 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 将第二个函数的最后一行标记为不安全的交叉线程。谁能建议我如何重写它来解决问题?

干杯

4

4 回答 4

4

使用System.Windows.Forms.Timer代替System.Timers.Timer

或使用Timer 的SynchronizingObject属性。

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

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

于 2012-08-21T09:33:59.597 回答
2

正如其他人建议的那样,使用System.Windows.Forms.Timer. 与System.Threading.Timer在线程池线程上运行的 不同,它保证在 UI 线程上调用滴答事件。

UI 线程是唯一允许修改 UI 的线程。这就是为什么您在尝试 write 时遇到异常的原因lbl_dyn_status.Text

于 2012-08-21T09:40:14.183 回答
1

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

于 2012-08-21T09:35:40.487 回答
0

将处理程序更改为

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,但会检查处理程序中的跨线程调用。如果检测到调用,则通过Form类在主 GUI 线程上调用。

在 MSDN 上有更详细的描述。

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

于 2012-08-21T09:42:27.193 回答