Search code examples
c#multithreadingtimer

C# Best Way to run a function every second, Timer vs Thread?


I am currently using a thread to run a function every second in a console application C# is a thread the best way to do it? As I have asked a lot of my friends and they have suggested using a timer not a thread for running something every second? If it is a better option to use a timer how would I go about running a function every second using a timer? I have looked around but I am really unsure if that applies to be and if its the right way of going about it in my own way. So can someone tell me the answer and how I can do it?

So what is the best way to run it every second? Before you answer let me just let you know that this is running every second for like 2 days... My current thread coding

namespace Reality.Game.Misc
{
    using Reality;
    using Reality.Communication.Outgoing;
    using Reality.Game.Rooms;
    using Reality.Game.Sessions;
    using Reality.Storage;
    using System;
    using System.Data;
    using System.Threading;

    public static class JobCacheWorker
    {
        private static Thread jWorkerThread;

        public static void HandleExpiration(Session Session)
        {
             using (SqlDatabaseClient client = SqlDatabaseManager.GetClient())
            {
                Session.CharacterInfo.UpdateWorking(client, 0);
            }
        }

        public static void Initialize()
        {
            jWorkerThread = new Thread(new ThreadStart(JobCacheWorker.ProcessThread));
            jWorkerThread.Priority = ThreadPriority.Highest;
            jWorkerThread.Name = "JobCacheWorker";
            jWorkerThread.Start();
        }

        public static void CheckEffectExpiry(Session Session)
        {
            try
            {
                //RunMyCodeHere...
            }
            catch (Exception exception)
            {
                    Console.WriteLine("Exception - JobCacheWorker -> " + exception.Message);
            } 
        }

        private static void ProcessThread()
        {
            while (Program.Alive)
            {
                try
                {
                    foreach (Session Session in SessionManager.Sessions.Values)
                    {
                        if (Session != null && Session.Authenticated && !Session.Stopped)
                        {
                            CheckEffectExpiry(Session);
                            Thread.Sleep(1000);
                        }
                    }
                }
                catch (ThreadAbortException exception)
                {
                    Output.WriteLine("ThreadAbortException - JobCacheWorker -> " + exception.Message);
                }
                catch (ThreadInterruptedException exception2)
                {
                    Output.WriteLine("ThreadInterruptedException - JobCacheWorker -> " + exception2.Message);
                }
            }
         }
    }
}

Solution

  • I'd use a System.Threading.Timer because it generally uses less resources than a devoted thread. Here's an example:

    using System;
    using System.Threading;
    
    namespace Demo
    {
        public static class Program
        {
            public static void Main()
            {
                Console.WriteLine("Starting timer with callback every 1 second.");
    
                Timer timer = new Timer(callback, "Some state", TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
    
                Thread.Sleep(4500); // Wait a bit over 4 seconds.
    
                Console.WriteLine("Changing timer to callback every 2 seconds.");
    
                timer.Change(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2));
    
                Thread.Sleep(9000);
    
                timer.Change(-1, -1); // Stop the timer from running.
    
                Console.WriteLine("Done. Press ENTER");
    
                Console.ReadLine();
            }
    
            private static void callback(object state)
            {
                Console.WriteLine("Called back with state = " + state);
            }
        }
    }
    

    This is a good choice for a Console app. However, you must of course bear in mind that the callback is still being done on a separate thread from the main thread, so you must be careful about synchronising resources and variables shared between the callback and the main thread.