Search code examples
c#timerthread-safetydatabase-connection

c# Timer to keep the sql-server connection to db "Alive"


I have met with the following problem. When the software does not make queries for long time, the connection to the database seems to go into a sleep mode, so that when I do perform a query it needs some time to wake-up. My solution to that is a timer defined in a static class that every 20 seconds does just this: opens and closes the connection. My question is, since the timer is asynchronous is my approach thread safe? This is my code.

 public static class Db
 {
    private static string connStr = "";
    private static System.Timers.Timer TimerConn = null;

     public static void Init(string theconnStr)
        {
            connStr = theconnStr;
            if (TimerConn!=null)
            {
                TimerConn.Enabled = false;
            }
            TimerConn = new System.Timers.Timer();
            TimerConn.Interval = 20000;
            TimerConn.Elapsed += HandleTimerConTick;

            TimerConn.Enabled = true;
        }


        private static void HandleTimerConTick(object source, ElapsedEventArgs e)
        {
            TestConnection();
        }
}


public static bool TestConnection()
        {
            try
            {
                SqlConnection con = new SqlConnection(connStr);
                con.Open();
                con.Close();
                return true;
            }
            catch
            {
                return false;
            }
        }

  }

Solution

  • Given the only shared state used is the connection string, yes it is thread-safe. If the connection string changes over time (which seems unlikely based on your code) then it may try and connect to an 'old version' of the connection string, but that is the worst behaviour that you might see. This won't be an issue if the connection string never changes.

    One thing to consider, to make it slightly cleaner, is to change to:

    try
    {
        using (SqlConnection con = new SqlConnection(connStr))
        {
            con.Open();
        }
        return true;
    }
    catch
    {
        return false;
    }
    

    to remove the need for the explicit Close call.

    Note, I am not commenting on whether your code is a good idea. It doesn't seem to be a particularly good idea to be continually connecting and disconnecting from the database like that, but that is outside the scope of your question. I would suggest only reconnecting every three minutes or so though, since normally connections are removed from the pool after four minutes.