【问题标题】:Repeating a function every few seconds每隔几秒重复一个功能
【发布时间】:2012-07-03 01:23:03
【问题描述】:

我想从程序打开的那一刻开始重复一个功能,直到它每隔几秒钟关闭一次。 在 C# 中执行此操作的最佳方法是什么?

【问题讨论】:

    标签: c# .net loops


    【解决方案1】:

    .NET BCL 中有很多不同的计时器:

    什么时候用哪个?

    • System.Timers.Timer,它会触发一个事件并定期在一个或多个事件接收器中执行代码。该类旨在用作多线程环境中的基于服务器或服务组件;它没有用户界面,在运行时不可见。
    • System.Threading.Timer,它定期在线程池线程上执行单个回调方法。回调方法是在定时器实例化时定义的,不能更改。与 System.Timers.Timer 类一样,此类旨在用作多线程环境中的基于服务器或服务组件;它没有用户界面,在运行时不可见。
    • System.Windows.Forms.Timer(仅限 .NET Framework),一种 Windows 窗体组件,它触发一个事件并定期在一个或多个事件接收器中执行代码。该组件没有用户界面,设计用于单线程环境;它在 UI 线程上执行。
    • System.Web.UI.Timer(仅限 .NET Framework),一个定期执行异步或同步网页回发的 ASP.NET 组件。
    • System.Windows.Threading.DispatcherTimer,一个集成到 Dispatcher 队列中的计时器。此计时器在指定的时间间隔以指定的优先级进行处理。

    Source


    其中一些需要明确的Start 调用才能开始计时(例如System.TimersSystem.Windows.Forms)。以及一个明确的Stop 来完成滴答声。

    using TimersTimer = System.Timers.Timer;
    
    static void Main(string[] args)
    {
        var timer = new TimersTimer(1000);
        timer.Elapsed += (s, e) => Console.WriteLine("Beep");
        Thread.Sleep(1000); //1 second delay
        timer.Start();
        Console.ReadLine();
        timer.Stop();
    
    }
    

    另一方面,有一些计时器(例如:System.Threading)您不需要明确的StartStop 调用。 (提供的委托将运行一个后台线程。)您的计时器将计时,直到您或运行时处理它。

    因此,以下两个版本将以相同的方式工作:

    using ThreadingTimer = System.Threading.Timer;
    
    static void Main(string[] args)
    {
        var timer = new ThreadingTimer(_ => Console.WriteLine("Beep"), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
        Console.ReadLine();
    }
    
    using ThreadingTimer = System.Threading.Timer;
    static void Main(string[] args)
    {
        StartTimer();
        Console.ReadLine();
    }
    
    static void StartTimer()
    {
        var timer = new ThreadingTimer(_ => Console.WriteLine("Beep"), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
    }
    

    但是如果你的timer 被释放,那么它显然会停止滴答作响。

    using ThreadingTimer = System.Threading.Timer; 
    
    static void Main(string[] args)
    {
        StartTimer();
        GC.Collect(0);
        Console.ReadLine();
    }
    
    static void StartTimer()
    {
        var timer = new ThreadingTimer(_ => Console.WriteLine("Beep"), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
    }
    

    【讨论】:

      【解决方案2】:

      使用计时器。有 3 种基本类型,每种都适用于不同的目的。

      仅在 Windows 窗体应用程序中使用。此计时器作为消息循环的一部分进行处理,因此可以在高负载下冻结计时器。

      当你需要同步时,使用这个。这意味着 tick 事件将在启动计时器的线程上运行,让您可以毫不费力地执行 GUI 操作。

      这是功能最强大的计时器,它在后台线程上触发滴答声。这使您可以在后台执行操作而不会冻结 GUI 或主线程。

      对于大多数情况,我推荐 System.Timers.Timer。

      【讨论】:

      • 只是一个补充——实际上不仅仅是这个——例如,还有DispatcherTimer(WPF/Silverlight),以及其他类似计时器的工具。
      • 另请注意,如果您设置 SynchronizingObject,System.Timers.Timer 的 elapsed 事件会在 UI 线程上触发,否则它会在 ThreadPool 线程上触发。
      • 需要注意的一点是,如果您想要可靠性,这些方法都不能在 100% 的时间内发挥作用,尤其是在负载较重的系统上。
      • 来自 MSDN 的重要说明:Timer 类仅在 .NET Framework 中可用。它不包含在 .NET 标准库中,并且在其他平台上不可用,例如 .NET Core 或通用 Windows 平台。在这些平台上,以及跨所有 .NET 平台的可移植性,您应该改用 System.Threading.Timer 类。
      • @JPelletier 谢谢你的评论让我很头疼。
      【解决方案3】:

      使用timer。请记住,.NET 带有许多不同的计时器。 This article 涵盖了差异。

      【讨论】:

      • MSDN 杂志链接已失效。
      【解决方案4】:

      为此,System.Timers.Timer 效果最好

      // Create a timer
      myTimer = new System.Timers.Timer();
      // Tell the timer what to do when it elapses
      myTimer.Elapsed += new ElapsedEventHandler(myEvent);
      // Set it to go off every five seconds
      myTimer.Interval = 5000;
      // And start it        
      myTimer.Enabled = true;
      
      // Implement a call with the right signature for events going off
      private void myEvent(object source, ElapsedEventArgs e) { }
      

      详情请见Timer Class (.NET 4.6 and 4.5)

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-17
      • 1970-01-01
      相关资源
      最近更新 更多