计时器未运行所有经过时间事件处理程序

4

我目前在定时器方面遇到问题。我想创建一个计时器,它会在按下按钮后执行。然后,它将从5开始倒数,并关闭从该类创建的窗口。以下是我目前拥有的内容:

public void startMessageIndicator(string message, bool completed)
{
      messageIndicator.Text = "completed";
      window.Show();
      aTimer = new System.Timers.Timer(5000);
      aTimer.Enabled = true;
      aTimer.Start();
      aTimer.Elapsed += new ElapsedEventHandler(timerElapsed);
      aTimer.AutoReset = true;
}

public void timerElapsed(object sender, ElapsedEventArgs e)
{
      window.Close();
      st.Clear();
      aTimer.Enabled = false;
}

当我编译代码时,没有任何问题,但是当我进入调试器并使用断点时,它似乎无法运行window.close(),只是停在那一行。

你有什么想法我做错了什么吗?


多余的闭合括号是做什么的? - JsonStatham
窗口是我通过类动态创建的表单。 - Khal786
抱歉,我的错。它进入了事件处理程序,但似乎没有运行 window.Close();。 - Khal786
你没有遇到跨线程异常吗? - Akansha
不,我没有遇到跨线程异常。 - Khal786
显示剩余2条评论
3个回答

2
你应该在窗口本身上调用一个调度程序来更新UI线程。
替换:
window.close();

使用

window.Invoke((MethodInvoker)delegate
            {
                window.Close();
            });

这与我的答案相同... window.Invokethis.Invoke 实际上是做同样的事情。 - Fabjan
@Fabjan 在你编辑代码之前就已经发布了答案。你之前的答案没有委托。所以我添加了它并发布了我的答案。 - Akansha

1
不要忘记,TimerTick 事件处理程序中的方法在单独的线程中执行,而 window 字段是在 UI 线程中创建的。尝试从与其创建时不同的线程调用方法会导致 InvalidOperationException... 因此,你可以简单地将代码更改为:
window.Close();

至:

this.Invoke(new Action(() => fr.Close()), null);

现在你在UI线程上调用操作,它应该按预期工作。

错误1:'practiceProgressBar2.Notifications'不包含定义为'Invoke'的内容,也没有接受类型为'practiceProgressBar2.Notifications'的第一个参数的扩展方法'Invoke'(您是否缺少使用指令或程序集引用?) - Khal786
在 Windows Forms 应用程序中,Invoke(new MethodInvoker(() => window.Close()), null); 对我很有效。 - Mitat Koyuncu
@Patrick,嗯,Tick事件确实在UI线程中执行,但它的处理程序不是。如果您在tick事件处理程序中添加Thread.Sleep(8000);,您将看到UI线程不会在8秒钟内冻结... - Fabjan

1
你可以使用这个。
ExecuteSecure(window.Close);
//OR
ExecuteSecure(() => window.Close());


//---
private void ExecuteSecure(Action action)
{
    if (InvokeRequired)
    {
        Invoke(new MethodInvoker(() => action()));
    }
    else
    {
        action();
    }
}

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