Multi-threaded app memory leak

J

J

Hi,

I've written a multi threaded application which scans about 2000
servers event logs to check for disk errors.

The problem with it is due to the fact that it just keeps eating
memory. In the end it's used up the best part of 100Mb, which I think
is excessive.

For each server it checks, it creates a new EventHelper object and
then executes a method which collects the data via a new thread. The
CheckEventLogs method rasies an event when it's completed and that
calls another method in the original code which writes the data to a
temp file.

Can anyone point me in the direction of what I'm doing wrong here and
the correct method for doing this?

Module1.vb #####################################################

Imports System.Threading

Module Module1

Dim RunningThreads As Integer = 0
Dim MaxThreads As Integer = 30

Sub Main()

RunProcess()

End Sub

Private Sub RunProcess()

If ServerList.Count = 0 Then End

Thread.CurrentThread.Name = "Main Thread"

Dim EventChecks(ServerList.Count - 1) As EventHelper
Dim t As Thread

For i As Integer = 0 To ServerList.Count - 1

EventChecks(i) = New EventHelper
EventChecks(i).ID = i
EventChecks(i).ServerName = ServerList(i)
AddHandler EventChecks(i).TaskCompleted, AddressOf
ProcessResults
t = New Thread(New ThreadStart(AddressOf
EventChecks(i).CheckEventLogs))
t.Name = String.Format("{0}", EventChecks(i).ID)
t.IsBackground = True
t.Start()
RunningThreads += 1

Do While RunningThreads >= MaxThreads + 1
Thread.Sleep(10000)
Loop

Next

Do Until RunningThreads = 0
Thread.Sleep(200)
Loop

End Sub

Private Function GetServerList() As ArrayList

Dim myList As New ArrayList

' Attains server list from source ....

Return myList

End Function


Private Sub ProcessResults(ByVal sender As Object)

RunningThreads -= 1

Dim Results As EventHelper = DirectCast(sender, EventHelper)

Dim id As String = Results.ID

Console.WriteLine("ThreadID {0} complete (Server: {1}).
Running processes: {2}. {3}", id, Results.ServerName, RunningThreads,
Results.ErrorMessage)

TempFileWriter.WriteTempFile(DirectCast(sender, EventHelper))

Results.Dispose()
Results = Nothing
sender = Nothing

End Sub

End Module

###############################################################

EventHelper.vb

Imports System.Management

Public Class EventHelper

Implements IDisposable

Event TaskCompleted(ByVal sender As Object)

Public ID As Integer = 0
Public ServerName As String = String.Empty
Public DaysToCheck As Double = 1.0
Public PhysicalDiskFail As Boolean = False
Public PredictiveDiskFail As Boolean = False
Public LogicalFail As Boolean = False
Public SANPathIssue As Boolean = False
Public BadBlock As Boolean = False
Public CorruptFilesystem As Boolean = False
Public BattteryFailure As Boolean = False
Public ErrorMessage As String = String.Empty

Public Sub New()

End Sub

Public Sub CheckEventLogs()

If Not ServerOnline(Me.ServerName) Then
ErrorMessage = String.Format("{0} - Server offline",
Me.ServerName)
RaiseEvent TaskCompleted(Me)
Exit Sub
End If

Me.ServerName = Me.ServerName.ToUpper.Trim

Dim EndDate As DateTime = Now
Dim StartDate As DateTime = DateAdd(DateInterval.Day, -
DaysToCheck, EndDate)

' Convert to WMI dates
Dim strEndDate As String = Year(EndDate) & Right("00" &
Month(EndDate), 2) & Right("00" & Day(EndDate), 2) & Right("00" &
Hour(Now), 2) & Right("00" & Minute(Now), 2) & "00.000000+060"
Dim strStartDate As String = Year(StartDate) & Right("00" &
Month(StartDate), 2) & Right("00" & Day(StartDate), 2) &
"000000.000000+060"

Dim SelectStatement As String = String.Format("Select * from
Win32_NTLogEvent Where TimeWritten >= '{0}' and TimeWritten < '{1}'
AND LogFile = 'system' and (SourceName = 'storage agents' OR
SourceName = 'CPQCISSE' OR SourceName = 'ntfs' OR SourceName =
'EmcpBase' OR SourceName = 'Disk') AND (EventType =1 OR EventType =
2)", strStartDate, strEndDate)

Dim Scope As ManagementScope
Dim Options As ConnectionOptions
Dim Query As ObjectQuery
Dim WMIInfo As ManagementObjectSearcher

Try

Scope = New ManagementScope
Options = New ConnectionOptions
Query = New ObjectQuery(SelectStatement)
WMIInfo = New ManagementObjectSearcher

With Options

.Impersonation = ImpersonationLevel.Impersonate
.Authentication = AuthenticationLevel.Packet

End With

Scope = New ManagementScope("\\" & Me.ServerName & "\root
\cimv2", Options)
Scope.Connect()

If Scope.IsConnected = False Then
Exit Sub
End If

WMIInfo.Scope = Scope
WMIInfo.Query = Query

For Each Info As ManagementObject In WMIInfo.Get

CheckForErrors(Info)

Next

Catch ex As Exception

ErrorMessage = String.Format("EventHelper: {0}",
ex.Message)

ErrorLogHelper.WriteError(String.Format("EventHelper:
{0}", ex.Message), Me.ServerName)

Finally

If Not IsNothing(WMIInfo) Then WMIInfo.Dispose()

RaiseEvent TaskCompleted(Me)

End Try

End Sub

Private Sub CheckForErrors(ByVal EventInfo As ManagementObject)

Dim EventCode As Int16 =
Convert.ToInt16(EventInfo("EventCode"))
Dim EventMsg As String = CStr(EventInfo("Message"))

Select Case EventCode

' Code removed for brevity

End Select

End Sub

Private Function ServerOnline(ByVal Server As String) As Boolean

Dim objStatus As ManagementObject
Dim objPing As New SelectQuery("Select StatusCode from
Win32_PingStatus WHERE Address = '" & Server & "' and statuscode = 0")
Dim Search As New ManagementObjectSearcher(objPing)

ServerOnline = (Search.Get.Count = 1)

objPing = Nothing
objStatus = Nothing
Search = Nothing

End Function

Public Overloads Sub Dispose() Implements IDisposable.Dispose

Dispose(True)
GC.SuppressFinalize(Me)

End Sub ' Dispose

Protected Overridable Overloads Sub Dispose(ByVal disposing As
Boolean)

If disposing Then

ID = Nothing
ServerName = Nothing
DaysToCheck = Nothing
PhysicalDiskFail = Nothing
PredictiveDiskFail = Nothing
LogicalFail = Nothing
SANPathIssue = Nothing
BadBlock = Nothing
CorruptFilesystem = Nothing
BattteryFailure = Nothing
ErrorMessage = Nothing

End If

End Sub ' Dispose

End Class
 
G

Guest

Can anyone point me in the direction of what I'm doing wrong here and
the correct method for doing this?

Threads use memory - perhaps look at using the Threadpool instead.

Also .NET will use memory until the GC kicks in, so don't worry too much
about memory usage unless it keeps going up and up and doesn't stablize.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top