Memory Leak Background Worker

bernies

New member
Joined
Oct 28, 2015
Messages
2
Programming Experience
Beginner
Hello,

First time post, and very new to code. I have written an application which polls a directory and copies any modified files since the last poll to another directory. The problem i'm getting is that i have a big memory leak that rapidly increases. I have tracked it down to this background worker but can't for the life of me work out where the problem is and am in need of a friendly hand! The background worker is called using this code!
I've confirmed this is the problematic code as if i disable the line that calls the background worker, there is no memory leak.
I think it may be around getting the directory files, but again am not too sure.

Thank you for your help.

VB.NET:
Dim PARAMS(3) As Object

           PARAMS(1) = Form2.tb_dj_audiodrop.Text
           PARAMS(2) = Form2.tb_dj_db.Text
           PARAMS(3) = Form2.tb_dj_audioprefix.Text

           If BW_Asend.IsBusy = True Then
              
           Else
               BW_Asend.Dispose()
               RUN_ASEND = 1
                BW_Asend.RunWorkerAsync(PARAMS)
           End if

Then the background worker does the following:

VB.NET:
On Error GoTo errorhandler

        Dim lastsynctime = LOAD_REGKEY("LAST_ASEND_TIME")

        Dim PARAMS(3) As Object
        PARAMS = e.Argument
        Dim PlaylistFolder As String = VT_Server.MYSQLQUERY("SELECT SETTINGS.[KEYVALUE] FROM SETTINGS WHERE SETTINGS.[KEY] LIKE 'playlistfolder'", PARAMS(2))
        Dim AudioFolder As String = VT_Server.MYSQLQUERY("SELECT SETTINGS.[KEYVALUE] FROM SETTINGS WHERE SETTINGS.[KEY] LIKE 'audiofolder'", PARAMS(2))
        Dim Profile2 = Form1.PROFILE
        If Profile2 = "" Then
            Profile2 = ""
        Else
            Profile2 = Profile2.Replace("_", ":")
        End If
        Dim ImportFolder As String = VT_Server.MYSQLQUERY("SELECT SETTINGS.[KEYVALUE] FROM SETTINGS WHERE SETTINGS.[Key] LIKE 'importfolder" & Profile2 & "'", PARAMS(2))
        PlaylistFolder = PlaylistFolder.TrimEnd(Path.DirectorySeparatorChar)
        AudioFolder = AudioFolder.TrimEnd(Path.DirectorySeparatorChar)
        ImportFolder = ImportFolder.TrimEnd(Path.DirectorySeparatorChar)
        Dim filepath = AudioFolder

        Dim directory As New System.IO.DirectoryInfo(filepath)
        Dim file = directory.EnumerateFiles()
        Dim file1 As FileInfo
        Dim filecount = directory.EnumerateFiles("*.*", SearchOption.TopDirectoryOnly).Count
        BW_Asend.ReportProgress(10, filecount)
        Dim x As Integer = 0


        For Each file1 In file
                x = x + 1
            BW_Asend.ReportProgress(20, x)
            Dim timenow = DateTime.UtcNow
            Dim modifieddatetime As DateTime = System.IO.File.GetLastWriteTimeUtc(filepath & "\" & file1.Name)
            Dim exisitingfilemodified As DateTime
            Dim extension = file1.Extension
            Dim filewithoutextension = file1.Name.ToString.Replace(extension, "")

            If modifieddatetime > lastsynctime Then
                Dim ID As String = file1.Name
                ID = ID.Replace(file1.Extension, "")
                Dim IMPORTER_TIME = VT_Server.MYSQLQUERY("SELECT AiImported FROM audio WHERE UID='" & ID & "'", PARAMS(2))
                If IMPORTER_TIME = "" Then
                    IMPORTER_TIME = DateTime.UtcNow.AddSeconds(10)
                End If
                Dim NEWIMPORTERTIME As DateTime = IMPORTER_TIME
                Dim importerdiff = DateDiff(DateInterval.Second, modifieddatetime, NEWIMPORTERTIME)

                If importerdiff <> 0 Then
                    If PARAMS(3) = "" = True Then
                        BW_Asend.ReportProgress(25, "Sending: " & file1.Name & " ---> " & PARAMS(1))
                        My.Computer.FileSystem.CopyFile(filepath & "\" & file1.Name, PARAMS(1) & "\" & file1.Name, True)
                    Else
                        Dim WILDCARD = InStr(file1.Name.ToString, PARAMS(3))
                        If WILDCARD = 1 Then
                            BW_Asend.ReportProgress(25, "Sending: " & file1.Name & " ---> " & PARAMS(1))
                            My.Computer.FileSystem.CopyFile(filepath & "\" & file1.Name, PARAMS(1) & "\" & file1.Name, True)
                        End If
                    End If
                End If
            End If
        Next

        SAVE_REGKEY("LAST_ASEND_TIME", DateTime.UtcNow)

errorhandler:
        If Err.Number <> 0 Then
            Dim message As String = Err.Number & " / " & Err.Description
            BW_Asend.ReportProgress(1, "FORM1.BW_ASEND " & message)
        End If



The progress changed event is as follows


VB.NET:
    On Error GoTo errorhandler
        If e.ProgressPercentage = 1 Then
            Dim message = e.UserState
            DebugLog(message)
        End If
        If e.ProgressPercentage = 10 Then
            BAR_ASEND_START = e.UserState
        End If
        If e.ProgressPercentage = 20 Then
            Dim temp = e.UserState / BAR_ASEND_START * 100
            BAR_ASEND.Value = temp
        End If
        If e.ProgressPercentage = 25 Then
            DebugLog(e.UserState)
        End If
errorhandler:
        ErrorHandler()
 
How have you identified a memory leak?

Dim Profile2 = Form1.PROFILE
This should not be done in a secondary thread. I understand you are just retrieving a string, but you should pass this when starting the work. Also if "Form1" is a default form reference then this statement will create a new form instance on secondary thread.

I don't see directly anything that could leak, but you have several method calls that could do that in their code, for example LOAD_REGKEY, MYSQLQUERY, SAVE_REGKEY and DebugLog.

Adding parameters to database queries by adding string variables is not a good practise, even if you can control any outcome of the constructed query, you should parameterize these.

Help about On Error said:
Whenever possible, we suggest you use structured exception handling in your code, rather than using unstructured exception handling and the On Error statement. For more information, see Try...Catch...Finally Statement (Visual Basic).

You can tidy up code several places using Path class and its methods like Combine and GetFileNameWithoutExtension.
 
Thank you John, I will make those changes as you have suggested.
In total there are 4 background workers, if I disable them all, the leak stops. I enabled one by one until the leak showed again. I first found it by the program showing a out of memory exception. I also noticed the heap growing out of control on each memory snap.
 
Back
Top