Memory Leaking in VB.NET

B

Brano

Hi all,

I have a VB.NET Dll that is invoked via BizTalk 2002 AIC over Http
protocol.

the Dll is making a connection using a 3rd party connector to a Unidata
database (old legacy stuff) All I am doing is creating an instance of
the class and then using its two methods (Connect CloseConnection)

and then setting the instance to Nothing.

However I am experiencing a big memory leak when I run stress test on
my DLL (the DLLHOST.EXE for the particular DLL goes up and up until it
crashes the server)

I have researched Garbage collector and used it but it doesnt help...

Here Is my code

Dim moudconn As New CUniData
moudconn.Connect(strResult)

moudconn.CloseConnection()

moudconn = Nothing

GC.Collect()
Dispose()

Can anybode see anything I am doing wrong??
 
N

NickP

Hi Brano,

Does your moudconn object have a dispose method?

If so call that before setting it to Nothing,

moudconn.Dispose()
moudconn = Nothing

... Hope this helps.

Nick.
 
B

Brano

Hi, It doesnt actually...

But I can access this class and reprogram it.

I have tried to add the microsoft code to do that which is:

Public MustInherit Class CUniDataBase
Implements IDisposable

' NB - ALWAYS CLOSE CONNECTION ON EXIT

' Pointer to an external unmanaged resource.
Private handle As IntPtr
' Other managed resource this class uses.
Private component As Component
' Track whether Dispose has been called.
Private disposed As Boolean = False

' The class constructor.
Public Sub New(ByVal handle As IntPtr)
Me.handle = handle
End Sub

' Implement IDisposable.
' Do not make this method virtual.
' A derived class should not be able to override this method.
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
' This object will be cleaned up by the Dispose method.
' Therefore, you should call GC.SupressFinalize to
' take this object off the finalization queue
' and prevent finalization code for this object
' from executing a second time.
GC.SuppressFinalize(Me)
End Sub

' Dispose(bool disposing) executes in two distinct scenarios.
' If disposing equals true, the method has been called directly
' or indirectly by a user's code. Managed and unmanaged
resources
' can be disposed.
' If disposing equals false, the method has been called by the
' runtime from inside the finalizer and you should not
reference
' other objects. Only unmanaged resources can be disposed.
Private Overloads Sub Dispose(ByVal disposing As Boolean)
' Check to see if Dispose has already been called.
If Not Me.disposed Then
' If disposing equals true, dispose all managed
' and unmanaged resources.
If disposing Then
' Dispose managed resources.
component.Dispose()
End If

' Call the appropriate methods to clean up
' unmanaged resources here.
' If disposing is false,
' only the following code is executed.
CloseHandle(handle)
handle = IntPtr.Zero
End If
disposed = True
End Sub

' Use interop to call the method necessary
' to clean up the unmanaged resource.
<System.Runtime.InteropServices.DllImport("Kernel32")> _
Private Shared Function CloseHandle(ByVal handle As IntPtr) As
[Boolean]
End Function

' This finalizer will run only if the Dispose method
' does not get called.
' It gives your base class the opportunity to finalize.
' Do not provide finalize methods in types derived from this
class.
Protected Overrides Sub Finalize()
' Do not re-create Dispose clean-up code here.
' Calling Dispose(false) is optimal in terms of
' readability and maintainability.
Dispose(False)
MyBase.Finalize()
End Sub


But if I cann the dispose now I get Object reference not set to an
instance of an object error...

;o(
 
A

AMDRIT

Brano,

Review this snippet and see if you can make use of the concepts within.

Public MustInherit Class CUniDataBase
Implements IDisposable

Private disposedValue As Boolean = False ' To detect redundant calls
Private myLegacy As Object ' Pointer to legacy database
Private myConnection As String ' Holds connection information
Private isInitialized As Boolean ' State flag of the unmanaged
object

Public Sub New(ByVal ConnectionString As String)

myConnection = ConnectionString

'myLegacy is not init'ed yet
isInitialized = False

End Sub

Public Sub Connect()

If Not isInitialized Then
myLegacy = CreateObject("SomeContainer.SomeObject")
myLegacy.Connection = myConnection
myLegacy.Connect()
isInitialized = True
End If

End Sub

Public Sub Disconnect()

If isInitialized AndAlso Not myLegacy Is Nothing Then
'Free up pointers
myLegacy.Disconnect()
End If

myLegacy = Nothing
isInitialized = False

End Sub

#Region " IDisposable Support "

' This code added by Visual Basic to correctly implement the disposable
pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing
As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub

' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: free unmanaged resources when explicitly called
Me.Disconnect()
End If
' TODO: free shared unmanaged resources
End If
Me.disposedValue = True
End Sub

Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub

#End Region

End Class


Brano said:
Hi, It doesnt actually...

But I can access this class and reprogram it.

I have tried to add the microsoft code to do that which is:

Public MustInherit Class CUniDataBase
Implements IDisposable

' NB - ALWAYS CLOSE CONNECTION ON EXIT

' Pointer to an external unmanaged resource.
Private handle As IntPtr
' Other managed resource this class uses.
Private component As Component
' Track whether Dispose has been called.
Private disposed As Boolean = False

' The class constructor.
Public Sub New(ByVal handle As IntPtr)
Me.handle = handle
End Sub

' Implement IDisposable.
' Do not make this method virtual.
' A derived class should not be able to override this method.
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
' This object will be cleaned up by the Dispose method.
' Therefore, you should call GC.SupressFinalize to
' take this object off the finalization queue
' and prevent finalization code for this object
' from executing a second time.
GC.SuppressFinalize(Me)
End Sub

' Dispose(bool disposing) executes in two distinct scenarios.
' If disposing equals true, the method has been called directly
' or indirectly by a user's code. Managed and unmanaged
resources
' can be disposed.
' If disposing equals false, the method has been called by the
' runtime from inside the finalizer and you should not
reference
' other objects. Only unmanaged resources can be disposed.
Private Overloads Sub Dispose(ByVal disposing As Boolean)
' Check to see if Dispose has already been called.
If Not Me.disposed Then
' If disposing equals true, dispose all managed
' and unmanaged resources.
If disposing Then
' Dispose managed resources.
component.Dispose()
End If

' Call the appropriate methods to clean up
' unmanaged resources here.
' If disposing is false,
' only the following code is executed.
CloseHandle(handle)
handle = IntPtr.Zero
End If
disposed = True
End Sub

' Use interop to call the method necessary
' to clean up the unmanaged resource.
<System.Runtime.InteropServices.DllImport("Kernel32")> _
Private Shared Function CloseHandle(ByVal handle As IntPtr) As
[Boolean]
End Function

' This finalizer will run only if the Dispose method
' does not get called.
' It gives your base class the opportunity to finalize.
' Do not provide finalize methods in types derived from this
class.
Protected Overrides Sub Finalize()
' Do not re-create Dispose clean-up code here.
' Calling Dispose(false) is optimal in terms of
' readability and maintainability.
Dispose(False)
MyBase.Finalize()
End Sub


But if I cann the dispose now I get Object reference not set to an
instance of an object error...

;o(
 
B

Brano

HI I think i have found the problem it is not my class because I have
rewritten the code from it to the main program and executed it and it
is creating the memory leek too.

The problem is I have a 3rd party class that doesnt have a dispose
method. It has however a OpenConnection method and a CloseConnection
method but I call both of these and the memory leak is still there. I
even set the object to Nothing afterwards but still the memory leek
appears. Here is snippet of my code :


Dim mobjUDConn As connection '# this object is declared in 3rd party
DLL that is referenced
Dim mobjUDDB As connDatabase '# this object is declared in 3rd
party DLL that is referenced

Const mcMultiDelim As String = "ý"
Const mcColumnDelim As String = "þ"

'# XXX means REMOVED FOR SECURITY PURPOUSES
Dim sHost As String = "XXX.x.XXX.xx"
Dim sPort As Int32 = XXXX
Dim sUser As String = String.Empty = "admin"
Dim sPassword As String = String.Empty = "XXXXXXX"
Dim sDatabase As String = String.Empty = "XXX-XXXXXXXX"

'#SUB CONNECT
Dim ErrMsg As String
Try
If mobjUDConn Is Nothing Then
mobjUDConn = New connection
End If
If mobjUDConn.isConnected = False Then
With mobjUDConn
.Host = sHost
.Port = sPort
.User = sUser
.Password = sPassword
.Database = sDatabase
mobjUDConn.open()
End With
End If
If mobjUDDB Is Nothing Then
mobjUDDB = New connDatabase
End If
If mobjUDDB.isConnected = False Then
mobjUDDB = mobjUDConn.getDatabase
End If
ErrMsg = ""
Catch ex As Exception
ErrMsg = ex.Message
End Try

'# Thats it connection opened
'# Do reads / writes here

'##### Close Connection ####
mobjUDDB.close()
'# ##### PROBLEM HERE #######
'# Problem is here mobjUDDB doesnt have a dispose method
mobjUDConn.close()
mobjUDConn.Dispose()

mobjUDDB = Nothing
mobjUDConn = Nothing
 
J

Jim Wooley

You might want to consider wrapping the 3rd party class that is leaking with
the USING functionality (in 2005). Another option to try is possibly wrap
the call and set up a second app domain which can be sandboxed. You then
create and destroy the app domain, thereby isolating the leak and disposing
of it. Granted there is a performance penalty with the second app domain
and the second domain must be stateless, but it might be a possibility.

Jim Wooley
 
B

Brano

Hi sounds good but I have never done anything like it. An example or
link would be great...

thanks
 

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