【问题标题】:How to enable a timer from a different thread/class如何从不同的线程/类启用计时器
【发布时间】:2009-04-07 13:35:24
【问题描述】:

原帖:How to access a timer from another class in C#

我什么都试过了。

-事件

-Invoke 无法完成,因为 Timers 没有 InvokeRequired 属性。

-公共/内部财产

没有任何效果,代码正在执行,timer.Enabled 属性被设置为“true”,但它没有 Tick。如果我调用事件或只是在 NON- 中更改表单类中的属性静态方法 - 它确实有效。

我从来不知道要花上一天甚至更多的时间才能学会如何使用一个像样的计时器。

如果没有办法做到这一点,还有什么我可以使用的类似于计时器的方法(延迟、启用/禁用)?

【问题讨论】:

  • 约翰,请将此添加到您之前的问题中(您可以编辑您的帖子),因为这对遇到相同问题的其他用户会更有帮助。

标签: c# winforms timer


【解决方案1】:

如果您需要多线程支持,您应该使用 System.Timers 命名空间中的 Timer 类,而不是 WinForms Timer 控件。查看 WinForms Timer 控件的 MSDN 文档以获取更多信息:

http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx

【讨论】:

  • 虽然这将触发 Elapsed 事件(System.Timer.Timer 有一个 Elapsed 事件,而不是 System.Windows.Forms.Timer 的 Tick 事件),但它将在上下文中触发调用线程,并且根据您在事件中执行的操作,可能会导致 System.InvalidOperationException,例如“跨线程操作无效:控件'X'从创建它的线程以外的线程访问。 "
  • 天才,我浪费了一天的时间。从来不知道 Windows 窗体计时器的怪癖。
  • 太棒了!为我工作。
【解决方案2】:

你不需要检查控件本身的InvokeRequired,你可以检查类的属性,例如:

if (this.InvokeRequired) 
{ 
    BeginInvoke(new MyDelegate(delegate()
    {
        timer.Enabled = true;
    }));
}

【讨论】:

    【解决方案3】:

    我不小心再次尝试使用invoke,这次成功了,但我会接受你的回答,DavidM。

        public bool TimerEnable
        {
            set
            {
                this.Invoke((MethodInvoker)delegate
                {
                    this.timer.Enabled = value;
                });
            }
        }
    
    
        public static void timerEnable()
        {
            var form = Form.ActiveForm as Form1;
            if (form != null)
                form.TimerEnable = true;
        }
    

    【讨论】:

    • 如果你的计时器在另一个班级怎么办?您将无法使用this 调用。我认为@David M 提供了一种可扩展的方法
    【解决方案4】:

    仅仅因为System.Windows.Forms.Timer 没有调用的能力,并不意味着你的表单没有。从第二个(或其他)线程尝试我的InvokeEx 以启用计时器。

    public static class ControlExtensions
    {
      public static TResult InvokeEx<TControl, TResult>(this TControl control,
                                Func<TControl, TResult> func)
        where TControl : Control
      {
        if (control.InvokeRequired)
        {
          return (TResult)control.Invoke(func, control);
        }
        else
        {
          return func(control);
        }
      }
    }
    

    有了这个,下面的代码对我有用:

    new Thread(() =>
      {
        Thread.Sleep(1000);
        this.InvokeEx(f => f.timer1.Enabled = true);
      }).Start();
    

    1 秒后计时器立即启动。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-10
      • 2020-04-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多