【问题标题】:Ending timer operation in User control在用户控制中结束定时器操作
【发布时间】:2015-01-21 09:45:16
【问题描述】:

我在用户控件中结束计时器操作时遇到问题。我通过一些操作创建了用户控件,使用 Timer 间隔发生。我想实现这个目标: 当用户使用我的用户控件关闭窗口时,操作(在 Calculate() 方法中)停止。这是我在MyUserControl.cs 中的代码:

   // fields
   private Timer timer; 

    // ctor
    public TestUserControl()
    {
       InitializeComponent();
       timer = new Timer();   
       timer.Tick += timer_Tick;
       timer.Interval = 5000;
       timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        Compute();
    }

    void ParentForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        timer.Stop();
    }

    private static void Compute()
    {
       // do something
    }

TestUserControl.Control.Desinger.csInitializeComponent() 方法中的这一行:

this.ParentForm.FormClosing += new System.Windows.Forms.FormClosingEventHandler(ParentForm_FormClosing);

但我在这一行中遇到异常:“System.NullReferenceException”类型的未处理异常

【问题讨论】:

  • 您为什么需要这样做?...当包含您的 UserControl 的表单关闭时,您的 Timer 将停止,并且 UserControl 与形式。现在,如果 Compute() 恰好在 Form 关闭时正在运行,那么它将在 Form 开始关闭过程之前完成(除非您使用 DoEvents 做了一些时髦的事情)。如果您需要 Compute() 过早停止,则必须修改该代码以定期检查某种“关闭”标志,以便它可以退出并允许表单继续正常关闭。
  • 我正在做一些数据库操作,每隔一段时间更新一次数据网格。我想在表单关闭时结束这个操作。
  • @Idle_Mind: “当包含你的 UserControl 的表单关闭时,你的 Timer 将被停止”——这不适用于 Timer 实例,就像这里的情况一样,明确声明并初始化,而不是通过设计器添加到控件中。
  • @PeterDuniho,你是对的;很好的收获。

标签: c# winforms .net-3.5


【解决方案1】:

您当前尝试的主要问题是,当从构造函数调用InitializeComponent() 方法时,控件还没有Parent 值。这就是异常告诉你的空值。

What is a NullReferenceException and how do I fix it?

解决此问题的最直接方法是首先删除所有Timer 初始化代码以及Timer 字段,然后使用设计器将Timer 添加到您的UserControl .那么你甚至不必首先订阅父母的FormClosing 事件。

您可以在设计器工具箱窗口的“组件”类别下找到Timer 对象。您可以拖动或双击它以将其添加到您的UserControl,就像任何其他工具箱项目一样。它不会放置在UserControl 本身上,而是放置在设计器自己的编辑窗口底部的区域中,供您的UserControl 使用。您可以在此处选择它并设置EnabledInterval 等属性,以及为Tick 事件添加事件处理程序。

如果您将其配置为将Enabled 属性设置为true,那么它将在您的UserControl 创建后立即启动。无论如何,通过以这种方式添加到UserControl,它会在控件自己的组件列表中结束,并在UserControl 本身被释放时自动释放(并因此停止),即当父窗体关闭时。

请注意,正如“Idle_Mind”的评论所指出的,因为您的 Tick 处理程序是在 UI 线程上执行的,所以在 UI 线程运行时不会发生任何其他事情。这意味着(除其他外)如果Compute() 方法需要一些时间才能完成,用户可能会感觉到从尝试关闭窗口到实际关闭窗口之间存在延迟。

由于在此期间甚至无法处理通常会发出关闭窗口信号的任何事件(例如鼠标单击、Alt+F4 等),真的没有什么好的方法可以改变这种行为(有一个不好的方法,我拒绝在这里描述)。在Compute() 方法完成之前,您甚至不会收到来自用户的信号。

如果您需要能够在运行时通过用户输入中断Compute() 方法,那么一种选择是使用System.Windows.Forms.Timer 以外的其他计时器,以便计时器处理程序将在单独的线程上运行并且让 UI 线程响应用户输入。另一种选择是将Compute() 方法更改为异步方法,这样即使定时器事件本身在UI 线程上处理,数据库操作也可以异步处理而不会阻塞UI 线程。任何一个选项都将是一个完全不同的问题,并且要获得一个好的答案,需要有关您的 Compute() 方法的具体详细信息,以显示您如何访问数据库和使用结果。 :)

【讨论】:

    猜你喜欢
    • 2018-04-14
    • 1970-01-01
    • 1970-01-01
    • 2014-07-27
    • 1970-01-01
    • 1970-01-01
    • 2020-10-16
    • 1970-01-01
    • 2023-03-14
    相关资源
    最近更新 更多