title: VB.NET Constantly polling a directory for files is causing an ongoing increase in memory usage
body: <p>I have a small application that on startup instantiates a class, reads in a JSON array from a text file and builds an object.  It then initialises a new <code>system.timers.timer</code> and scans a directory every xx minute(s) to get a file count.</p>
  
  <p>When my application starts up, Windows Task Manager shows it at around 13MB of Memory, however, leaving it to run for about 12 hours now shows it at 700+MB of Memory when no files were even detected in this directory.  I'm worried that this is just going to grow forever and eventually crash.  It doesn't seem like anything is getting cleaned up by the <code>GC</code> (probably because my timer and objects are always active).</p>
  
  <p>Although this class is quite simple in theory, I do have other functions and timers involved that don't get called until required.  I am happy to post all my code somewhere, or even just the class, but it's a little too long to add to this post.</p>
  
  <p>I have included the main elements of my class however:</p>
  
  <pre><code>Public Sub Initialize()
          Try
              If AgentSettings.DebugMode Then CreateLog("Entered Module: Initialize()")
  
  
  
              CreateLog("Initializing Alerting Rule: &lt;" &amp; Me.Name &amp; "&gt;")
              CreateLog("Validating all Rule Profiles")
  
  
  
              'Loop through all the Rule Profiles and make sure they are all valid
              'If not, disable the profile so it never scans
              For Each profile As RuleProfile In Me.RuleProfiles
  
  
  
                  CreateLog("Verifying Profile: &lt;" &amp; profile.Name &amp; "&gt;")
  
  
  
                  'Check to make sure the Profile is functionally valid
                  If ProfileIsValid(profile) Then
  
  
  
                      'Profile is valid so setup an event handler to handle the isBroken event
                      profile.Active = True
                      CreateLog("Rule Profile: &lt;" &amp; profile.Name &amp; "&gt; Enabled")
                      AddHandler profile.BrokenStatusChanged, AddressOf CheckIfRuleIsBroken
  
  
  
                  Else
  
  
  
                      'Disable the Profile
                      CreateLog("Rule Profile: &lt;" &amp; profile.Name &amp; "&gt; Disabled")
                      profile.Active = False
  
  
  
                  End If
  
  
  
              Next
  
  
  
              'Setup the checking timer and set the interval to the default checking time
              If Me.ruleCheckTimer Is Nothing Then
  
  
  
                  Me.ruleCheckTimer = New System.Timers.Timer
                  Me.ruleCheckTimer.AutoReset = True
                  Me.ruleCheckTimer.Interval = Me.DefaultMinutesToCheck * 60000
                  AddHandler Me.ruleCheckTimer.Elapsed, AddressOf CheckRule
  
  
  
              End If
  
  
              'If there is an escalation plan then setup a timer for it
              If Me.EscalationPlan.PlanItems.Count &gt; 0 Then
  
  
  
                  'Setup the escalation timer and set the interval to the first plan item
                  If Me.escalationTimer Is Nothing Then
  
  
  
                      Me.escalationTimer = New System.Timers.Timer
                      Me.escalationTimer.AutoReset = True
                      AddHandler Me.escalationTimer.Elapsed, AddressOf Escalate
  
  
  
                  End If
  
  
  
              End If
  
  
  
          Catch ex As Exception
              CreateLog("Module: Initialize()" &amp; vbNewLine &amp; "Exception Error: " &amp; ex.Message)
  
  
          End Try
      End Sub
  
  
  Private Sub CheckRule(ByVal sender As Object, ByVal e As EventArgs)
          Try
              If AgentSettings.DebugMode Then CreateLog("Entered Module: CheckRule()")
  
  
  
              'Loop through all the profiles
              For Each profile As RuleProfile In Me.RuleProfiles
  
  
  
                  CreateLog("Scanning for active profiles")
  
  
  
                  'Make sure the Profile is active
                  If profile.Active Then
  
  
  
                      Select Case profile.Name
  
  
  
                          Case "FileCount"
  
  
  
                              CreateLog("Checking Rule Profile: &lt;" &amp; profile.Name &amp; "&gt; for isBroken status")
  
  
  
                              'Get file count of the specified directory
                              Dim files As String()
                              files = Directory.GetFiles(profile.DirectoryPath)
  
  
  
                              'Determine if we're checking for files greater than or less than
                              If profile.GreaterThan Then
  
  
  
                                  If files.Count &gt; profile.FileCount Then
  
  
  
                                      profile.isBroken = True
  
  
  
                                  Else
  
  
  
                                      profile.isBroken = False
  
  
  
                                  End If
  
  
  
                              Else
  
  
  
                                  If files.Count &lt; profile.FileCount Then
  
  
  
                                      profile.isBroken = True
  
  
  
                                  Else
  
  
  
                                      profile.isBroken = False
  
  
  
                                  End If
  
  
  
                              End If
  
  
  
                              files = Nothing
  
  
  
                      End Select
  
  
  
                  End If
  
  
  
              Next
  
  
  
          Catch ex As Exception
              CreateLog("Module: CheckRule()" &amp; vbNewLine &amp; "Exception Error: " &amp; ex.Message)
  
  
          End Try
      End Sub
  </code></pre>
  
  <p>When <code>profile.isBroken</code> receives an update, it triggers an event which then loops through all profiles to determine which ones are broken.  If all are broken, then it begins its alerting and escalation process.  However, none of this is occurring and my memory is still increasing constantly.</p>
  
  <p>Can anyone see anything wrong with this?  Or maybe a better way (and more efficient way) of polling this directory?</p>
  
  <p>The theory behind my application is to instantiate multiple classes to allow various directories or files to be scanned, but if the memory has increased this much with just the one instance, I'm concerned about running multiple.</p>
  
  <p><strong>EDITED</strong></p>
  
  <p>My log handling is as follows:</p>
  
  <pre><code>Public Sub CreateLog(ByVal text As String)
      Try
          'Create Log Directory if it doesn't exist
          If (Not System.IO.Directory.Exists(GetFolderPath(SpecialFolder.CommonApplicationData) &amp; "\MyCompany\Agent\Log")) Then System.IO.Directory.CreateDirectory(GetFolderPath(SpecialFolder.CommonApplicationData) &amp; "\MyCompany\Agent\Log\")
  
  
  
          'Write log entry
          LogFile = GetFolderPath(Environment.SpecialFolder.CommonApplicationData) &amp; "\MyCompany\Agent\Log\" &amp; "Logfile - " &amp; Format(Now, "ddMMyyyy") &amp; ".txt"
          File.AppendAllText(LogFile, DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss") &amp; "  " &amp; text &amp; Environment.NewLine)
  
  
  
          'Update the activity text on the main UI
          frmMain.UpdateActivityText(text)
  
  
  
      Catch ex As Exception
          'No need to create a log entry
  
  
      End Try
  End Sub
  </code></pre>