I have set up a threaded timer that will fire every x seconds (in this case every 5 seconds) checks a directory (in this case all .log files (4 in total) if it picks up a log file has changed it will take the new lines and send them off to be logged to Log Stash. This app will be running as a Windows service on a Windows Server 2012 box.
this is working as it stands, however I want to make sure that i am not in danger of letting me threads get out of hand and cause massive cpu issues on the server.
I am not interesting in the solution that i have to check if a file has changed, what I am interested in is peoples opinion on the threads and and any improvements/safe guards i need to put in place to prevent cpu leakage.
here is my code:
    protected override void OnStart(string[] args)
    {
        var statusChecker = new LogFileMonitor(@"C:\DEV\LOGS\", "\r\n");
       // _timer = new Timer(statusChecker.CheckStatus,
         //   null, 1000, 30000);
       //_timer = new Timer(statusChecker.CheckStatus, null, 5000, Timeout.Infinite);
        _timer = new Timer((g) =>
        {
            statusChecker.CheckStatus();
            _timer.Change(5000, Timeout.Infinite);
        }, null, (long) 0, Timeout.Infinite);
    }
public class LogFileMonitor
    {
        private string Delimiter = String.Empty;
        private List<LogFileInfo> LogFileInfo;
        private string _buffer = "";
        private readonly LogStashHelper _logStashHelper;
        private volatile bool _executing = false;
        public LogFileMonitor(string path, string delimiter = "\n")
        {
            var logList = new List<LogFileInfo>();
            var logStashHelper = new LogStashHelper();
            string[] files = Directory.GetFiles(path, "*.log", SearchOption.AllDirectories);
            foreach (var fileName in files)
            {
                var createDate = new FileInfo(fileName).CreationTime;
                var size = new FileInfo(fileName).Length;
                logList.Add(new LogFileInfo(fileName, size, createDate));
            }
            _logStashHelper = logStashHelper;
            LogFileInfo = logList;
            Delimiter = delimiter;
        }
        // This method is called by the timer delegate.
        public void CheckStatus()
        {
            if (_executing)
                return;
            _executing = true;
            var index = 0;
            try
            {
                foreach (var fileInfo in LogFileInfo)
                {
                    var fileName = fileInfo.FileName;
                    var originalSize = fileInfo.FileSize;
                    var currentCreateDate = fileInfo.FileCreateDate;
                    Console.WriteLine("checking file: " + fileName);
                    // get the new size
                    var newSize = new FileInfo(fileInfo.FileName).Length;
                    //get the new date creation
                    var newCreateDate = new FileInfo(fileInfo.FileName).CreationTime;
                    if (currentCreateDate < newCreateDate)
                    {
                        //then we have a new file reset defai
                        _buffer = String.Empty;
                        LogFileInfo[index].FileSize = new FileInfo(fileInfo.FileName).Length;
                        LogFileInfo[index].FileCreateDate = new FileInfo(fileInfo.FileName).CreationTime;
                        newSize = new FileInfo(fileInfo.FileName).Length;
                        originalSize = 0;
                    }
                    if (originalSize >= newSize)
                    {
                        //do nothing
                    }
                    else
                    {
                        // read the contents of the file
                        using (
                            var stream = File.Open(fileName, FileMode.Open, FileAccess.Read,
                                FileShare.ReadWrite))
                        using (var sr = new StreamReader(stream))
                        {
                            // seek to the current file position
                            sr.BaseStream.Seek(originalSize, SeekOrigin.Begin);
                            // read from current position to the end of the file
                            var newData = _buffer + sr.ReadToEnd();
                            // if we don't end with a delimiter we need to store some data in the buffer for next time
                            if (!newData.EndsWith(Delimiter))
                            {
                                // we don't have any lines to process so save in the buffer for next time
                                if (newData.IndexOf(Delimiter, System.StringComparison.Ordinal) == -1)
                                {
                                    _buffer += newData;
                                    newData = String.Empty;
                                }
                                else
                                {
                                    // we have at least one line so store the last section (without lines) in the buffer
                                    var pos =
                                        newData.LastIndexOf(Delimiter, System.StringComparison.Ordinal) +
                                        Delimiter.Length;
                                    _buffer = newData.Substring(pos);
                                    newData = newData.Substring(0, pos);
                                }
                            }
                            // split the data into lines
                            var lines = newData.Split(new string[] {Delimiter},
                                StringSplitOptions.RemoveEmptyEntries);
                            //List<string> text = File.ReadLines("file.txt").Reverse().Take(2).ToList();
                            // send back to caller, NOTE: this is done from a different thread!
                            foreach (var line in lines)
                            {
                                _logStashHelper.SendToLogStash(line, MessageCategory.Information,
                                    new Dictionary<object, object>(), fileName);
                            }
                            stream.Close();
                        }
                        // set the new current position
                        LogFileInfo[index].FileSize = newSize;
                    }
                    index++;
                }
            }
            catch (Exception e)
            {
            }
            finally
            {
                _executing = false;
            }
        }
    }
