Memory Leak when throwing exception in VB .NET

Hello All,

I have an VB .NET application for CF that throws an exception in a Threading.Timer. This seems to be leaking memory. A Forms.Timer works ok)

Stripped down the problemsource looks like this. The GC.Collect is just there for the remote performance monitor. I monitor the Managed Bytes In Use After GC ANd this keeps running up. I I compare GC Heaps I guess it is a ErrObject that is not released. I do not understand however how to do that.

Thanks in advance for any help.

Module Module1

  Public timMain As clsTimer = Nothing

  Sub Main()
    timMain = New clsTimer
    While True
    End While
  End Sub
  Public Class Test
    Sub ThrowEx()
      Try
        'This leaks
        Throw New Exception
      Catch ex As Exception
        ex = Nothing
        ' for NETCFRPM
        GC.Collect()
      End Try
    End Sub
  End Class

  Public Class clsTimer
    Delegate Sub DoSomething()
    Dim timTimer As System.Threading.Timer

    Public Sub New()
      timTimer = New System.Threading.Timer(AddressOf mHandleTimer, Nothing, 0, System.Threading.Timeout.Infinite)
    End Sub

    Private Sub mHandleTimer(ByVal source As Object)
      Dim clsTest As New Test
      Dim myThrowEx As DoSomething = AddressOf clsTest.ThrowEx
      myThrowEx.Invoke()
      timTimer.Change(1000, System.Threading.Timeout.Infinite)
      clsTest = Nothing
      myThrowEx = Nothing
    End Sub
  End Class


End Module


 
IrDuckAsked:
Who is Participating?
 
multithreadingCommented:
You don't have an actual "leak", it just looks that way. Your code is allocating little chunks of memory at at time. If you watch the memory allocation, it will keep climbing, and climbing, and climbing -- but always by little amounts. That is because the garbage collector is lazy. It doesn't kick in just because you have objects out there. It kicks in when the time feels right. Eventually it will level off. The GC is like a thermostat in your house. It doesn't kick on and off constantly. Ironically, if you were allocating bigger chunks of memory, it would force the GC to kick in quicker, and you would see your memory utilization more constant than it is in your program.

"Oh, but wait" ... "I have a GC.Collect() in there". Yes, but that is buried inside of memory allocations. If you were to move the GC.Collect() from where it is to the bottom of the mHandleTimer method, you would see memory stay much more stable. (You don't need to force the Collect at all, of course, it will kick in by itself eventually. Moreover, it is usually best not to force it, but I know you are doing this just for testing purposes.)

I know it is just a stripped down test, but if you would like to stop pegging your CPU at 100% utilization, change your
   While True
    End While
to something like
           System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite)

Now, there is one more lingering question: "Why didn't it behave this way in my forms application?" Your forms application is allocating memory constantly. All of the little window events generate messages, which often result in managed allocations, which keeps the GC humming more frequently.
0
 
dctuckCommented:
Try disposing of your timer once you are finished with it:

timTimer.Dispose()
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
IrDuckAuthor Commented:
Thanks, but actually the timer is not supposed to stop in the program. It is used to check if any file handling needs to be done, and runs as long as the program runs. I have however tested disposing the timer at a certain point but that does not return the memory leaked by the Exception throwing. In the .NET CF Remote Performance Monitor it is just the err.object and relates stuff that grows in instances, not the timer.

 
0
 
IrDuckAuthor Commented:
Hi, Thanks for the clear explanation. Maybe I am looking at the wrong thing. (Sometimes you mess up more by monitoring than you solve). However, I ran a Device Application version of this program for a long time and it actually crashed on a memory error. I have tried to run this console application for a long time this morning on reduced memory, and actually after a few hours the device became much slower.  I move the GC.Collect as you suggested and ran the program through NETCFRPM but still noticed the value Managed Bytes After GC running up (as far as I know that is an indication for a memory leak). I run the program on CE 5.0 and CF 2.0. (In real life btw there is no GC.Collect in the program and the exception is only thrown in certain circumstances so the memory will last for about a weak before a reset is needed.) Hope you have some more suggestions, thanks in advance.  
0
 
multithreadingCommented:
I don't have Console capability on my CE device. Someone else is going to have to jump in here. It looks like it is specific to console applications on CE as your code runs without leaking on XP.
0
 
multithreadingCommented:
It was an aside earlier, but maybe the garbage collector thread is competing with your CPU-bound infinite loop in your Main. That thing really jumps off the page.

  While True
   End While

If you want to wait forever, use System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.