private void ReadLogFile()
 {
     _running = true;
     _offset  = FindInitialOffset();
     Util.DebugLog?.WriteLine($"LogWatcher.ReadLogFile: offset={_offset}");
     while (!_stop)
     {
         var fileInfo = new FileInfo(_info.FilePath);
         if (fileInfo.Exists)
         {
             if (!_logFileExists)
             {
                 _logFileExists = true;
                 OnLogFound?.Invoke(this, new LogFoundEventArgs(_info.Name));
                 Util.DebugLog?.WriteLine("LogWatcher.ReadLogFile: found " + _info.Name);
             }
             using (var fs = new FileStream(_info.FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
             {
                 fs.Seek(_offset, SeekOrigin.Begin);
                 if (fs.Length == _offset)
                 {
                     Thread.Sleep(_readDelay);
                     continue;
                 }
                 var lines = new List <LogLineItem>();
                 using (var sr = new StreamReader(fs))
                 {
                     string line;
                     while (!sr.EndOfStream && (line = sr.ReadLine()) != null)
                     {
                         if (line.StartsWith("D "))
                         {
                             var next = sr.Peek();
                             if (!sr.EndOfStream && !(next == 'D' || next == 'W'))
                             {
                                 break;
                             }
                             var logLine = new LogLineItem(_info.Name, line);
                             if ((!_info.HasFilters || (_info.StartsWithFilters?.Any(x => logLine.LineContent.StartsWith(x)) ?? false) ||
                                  (_info.ContainsFilters?.Any(x => logLine.LineContent.Contains(x)) ?? false)) &&
                                 logLine.Time >= _startingPoint)
                             {
                                 lines.Add(logLine);
                             }
                         }
                         else
                         {
                             OnIgnoredLine?.Invoke(this, new RawLogLineEventArgs(line));
                         }
                         _offset += Encoding.UTF8.GetByteCount(line + Environment.NewLine);
                     }
                 }
                 OnNewLine?.Invoke(this, new LogLineEventArgs(lines));
             }
         }
         Thread.Sleep(_readDelay);
     }
     _running = false;
 }
        private long FindInitialOffset()
        {
            var fileInfo = new FileInfo(_info.FilePath);

            if (fileInfo.Exists)
            {
                using (var fs = new FileStream(_info.FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    using (var sr = new StreamReader(fs, Encoding.ASCII))
                    {
                        var offset = 0;
                        while (offset < fs.Length)
                        {
                            var sizeDiff = 4096 - Math.Min(fs.Length - offset, 4096);
                            offset += 4096;
                            var buffer = new char[4096];
                            fs.Seek(Math.Max(fs.Length - offset, 0), SeekOrigin.Begin);
                            sr.ReadBlock(buffer, 0, 4096);
                            var skip = 0;
                            for (var i = 0; i < 4096; i++)
                            {
                                skip++;
                                if (buffer[i] == '\n')
                                {
                                    break;
                                }
                            }
                            offset -= skip;
                            var lines = (new string(buffer.Skip(skip).ToArray())).Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToArray();
                            for (int i = lines.Length - 1; i > 0; i--)
                            {
                                if (string.IsNullOrWhiteSpace(lines[i].Trim('\0')))
                                {
                                    continue;
                                }
                                var logLine = new LogLineItem(_info.Name, lines[i]);
                                if (logLine.Time < _startingPoint)
                                {
                                    var negativeOffset = lines.Take(i + 1).Sum(x => Encoding.UTF8.GetByteCount(x + Environment.NewLine));
                                    return(Math.Max(fs.Length - offset + negativeOffset + sizeDiff, 0));
                                }
                            }
                        }
                    }
            }
            return(0);
        }