JohnWick
JohnWick

Reputation: 5149

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

Upvotes: 0

Views: 936

Answers (1)

Visual Vincent
Visual Vincent

Reputation: 18310

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()

Upvotes: 1

Related Questions