Search code examples
c#timertiming

C# Proper way of periodically firing functions


I've got about 20 functions, some of them should be fired once a second, some, 20 times a second and other twice a minute currently I have something like this:

                DateTime nowVar = DateTime.Now;
                var lastExecutionFunc1 = nowVar;
                var lastExecutionFunc2 = nowVar;
                var lastExecutionFunc3 = nowVar;
                var lastExecutionFunc4 = nowVar;

        DateTime _now = DateTime.Now;


                if ((_now - lastExecutionFunc1).TotalSeconds >= 0.1)
                        {
                            lastExecutionFunc1 = _now;
                            //dosomething
                        }
               if ((_now - lastExecutionFunc2).TotalSeconds >= 0.5)
                        {
                            lastExecutionFunc2 = _now;
                            //do something else
                        }
               if ((_now - lastExecutionFunc3).TotalSeconds >= 30)
                        {
                            lastExecutionFunc3 = _now;
                            //do something else
                        }
.....

While this works, I can't help but think that there should be a more elegant way of doing this. Creating a var to store each execution makes the core look really messy. Guess I could use pair, but that wouldn't be too nice either.

Any advice?

EDIT: If you want to see what I'm trying to accomplish, you can see the whole code here. At line 525.


Solution

  • Below code presents a basic scheduler with synchronisation lock.

    using System;
    using System.Collections.Generic;
    using System.Timers;
    
    namespace TimerUsage
    {
        class Program
        {
            static void Main(string[] args)
            {
                Scheduler scheduler = new Scheduler();
                scheduler.ScheduleMethod(100, () => Console.WriteLine("func1"));
                scheduler.ScheduleMethod(200, () => Console.WriteLine("func2"));
                scheduler.ScheduleMethod(300, () => Console.WriteLine("func3"));
                scheduler.ScheduleMethod(1000, () => Console.WriteLine("func4"));
                scheduler.Run();
                System.Threading.Thread.Sleep(10000);
            }
    
        }
    
        public class Scheduler
        {
            private Dictionary<int, Row> _schedule = new Dictionary<int, Row>();
    
            public void ScheduleMethod(int interval, Action method)
            {
                Row row;
                if (!_schedule.TryGetValue(interval, out row))
                {
                    row = new Row(interval);
                    _schedule[interval] = row;
                }
                row.AddMethod(method);
            }
    
            public void Run()
            {
                foreach (var item in _schedule)
                {
                    item.Value.StartTimer();
                }
            }
        }
    
        internal class Row
        {
            private object _syncLock = new object();
            private Timer _timer;
            private List<Action> _methods = new List<Action>();
    
            public Row(int interval)
            {
                _timer = new System.Timers.Timer(interval);
                _timer.Elapsed += ExecuteItems;
            }
    
            private void ExecuteItems(object sender, ElapsedEventArgs e)
            {
                lock (_syncLock)
                {
                    foreach (var method in _methods)
                    {
                        method();
                    }
                }
            }
    
            public void AddMethod(Action method)
            {
                _methods.Add(method);
            }
    
            public void StartTimer()
            {
                _timer.Start();
            }
    
        }
    
    }