David Stampher David Stampher - 4 months ago 27
Vb.net Question

VB.Net Dispose/Garbage Collector not releasing resources?

using VS 2015 here...just made a small testing program to compare the performance difference between an async webrequest using tasks and the way I was doing it before with HttpWebRequest.BeginGetResponse

But the point is I tried to dispose of the state object I was using for the async requests by implementing IDispoable, but in my diagnostics it shows that the allocated RAM size remains the same? I was under the impression that calling dispose would release the resources the object was using? Here is the code I am using, I also tried just setting the object to Nothing.

Imports System.Net

Public Class Form1
Private sw As New Stopwatch

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim req As HttpWebRequest = HttpWebRequest.Create("http://example.com")
Dim state As New RequestState
state.req = req
req.BeginGetResponse(AddressOf respCallback, state)
End Sub

Private Sub respCallback(ar As IAsyncResult)
Dim state As RequestState = ar.AsyncState
state.resp = state.req.EndGetResponse(ar)
state.respStream = state.resp.GetResponseStream
state.respStream.BeginRead(state.buffer, 0, 1024, AddressOf readCallback, state)
End Sub

Private Sub readCallback(ar As IAsyncResult)
Dim state As RequestState = ar.AsyncState
Dim read As Integer = state.respStream.EndRead(ar)
If read > 0 Then
state.respBody += System.Text.ASCIIEncoding.ASCII.GetString(state.buffer, 0, read)
state.respStream.BeginRead(state.buffer, 0, 1024, AddressOf readCallback, state)
Else
state.respStream.Close()
MsgBox(state.respBody)
state.Dispose()
End If
End Sub

Public Class RequestState
Implements IDisposable

Public req As HttpWebRequest
Public resp As HttpWebResponse
Public respStream As IO.Stream
Public buffer(1024) As Byte
Public respBody As String

#Region "IDisposable Support"
Protected Overridable Sub Dispose(disposing As Boolean)
If Not disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
req = Nothing
resp.Close()
resp.Dispose()
resp = Nothing
respStream.Close()
respStream.Dispose()
respStream = Nothing
buffer = Nothing
respBody = Nothing
End If

' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
disposedValue = True
End Sub

' TODO: override Finalize() only if Dispose(disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub

' 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(disposing As Boolean) above.
Dispose(True)
' TODO: uncomment the following line if Finalize() is overridden above.
' GC.SuppressFinalize(Me)
End Sub
#End Region
End Class

Answer

Simply implementing IDisposable doesn't automatically free up memory, all that is up to the programmer to release managed and unmanaged resources.

In the Dispose(disposing As Boolean) method you would have to call Close() or Dispose() on each of your variables that implement the disposing functionality:

Protected Overridable Sub Dispose(disposing As Boolean)
    If Not disposedValue Then
        If disposing Then
            'Here you dispose all managed resources.
            respStream.Close()
            respStream.Dispose()
            resp.Close()
        End If
    End If
    disposedValue = True
End Sub

When you are done with your asynchronous actions, be sure to close the IAsyncResult.AsyncWaitHandle object. You should be able to do this in the end of every callback method:

ar.Close()
Comments