user2980316
user2980316

Reputation: 149

Unload/Remove vb Resource from Memory

I'm extremely new to programming and have still to master a lot of the basics. But I've managed to make an entire Program with help from here and there. However, I think I've got a Memory Leak with regards to my resources, again I'm new and almost certain this is a clumsy way to go about doing this...

I currently have background music in my application which uses a .wav file stored in My.Resources. I've implemented multiple measures to enable, disable and mute the audio successfully, but I've hit a snag when I introduced multiple audio tracks. The idea is to give the end-user an option between 4 background songs (stored as 4 .wav resources) in the 'settings' area of my program. When I build & test the solution it runs great, everything as expected. Then when I change the audio to a different track in the settings area, it works also. The snag happens when I change the song multiple times, I get a OutOfMemory error.

I think I understand what's happening; the resource is being added to the memory each time the user selects it, But I have no idea on how to remove -say- song1 from the memory if -say- song2 is selected. Here's my code which handles the selection & playing of the audio.

(The program uses radio buttons refereed to as '%chkbox' and requires the user to hit 'savebtn' before this code is ran.) Using Visual Basics 2012 .net 4.5

    'Save and start songs.

    If DjErhain_Mistychkbox.Checked = True Then
        My.Settings.AudioDJErhain_UWBeats_Maniac = 0
        My.Settings.Save()
        My.Settings.AudioDjErhain_Misty = 1
        My.Settings.Save()
        My.Settings.AudioMachinimaSound_Exigence = 0
        My.Settings.Save()
        My.Settings.AudioSimplex_Memories_master = 0
        My.Settings.Save()

        My.Computer.Audio.Play(My.Resources.DjErhain_Misty, AudioPlayMode.BackgroundLoop)


    ElseIf DJErhain_UWBeats_Maniacckbox.Checked = True Then
        My.Settings.AudioDjErhain_Misty = 0
        My.Settings.Save()
        My.Settings.AudioDJErhain_UWBeats_Maniac = 1
        My.Settings.Save()
        My.Settings.AudioMachinimaSound_Exigence = 0
        My.Settings.Save()
        My.Settings.AudioSimplex_Memories_master = 0
        My.Settings.Save()

        My.Computer.Audio.Play(My.Resources.DJErhain_UWBeats_Maniac, AudioPlayMode.BackgroundLoop)


    ElseIf MachinimaSound_Exigencechckbox.Checked = True Then
        My.Settings.AudioMachinimaSound_Exigence = 1
        My.Settings.Save()
        My.Settings.AudioDJErhain_UWBeats_Maniac = 0
        My.Settings.Save()
        My.Settings.AudioDjErhain_Misty = 0
        My.Settings.Save()
        My.Settings.AudioSimplex_Memories_master = 0
        My.Settings.Save()

        My.Computer.Audio.Play(My.Resources.MachinimaSound_Exigence, AudioPlayMode.BackgroundLoop)


    ElseIf Simplex_Memories_masterchckbox.Checked = True Then
        My.Settings.AudioSimplex_Memories_master = 1
        My.Settings.Save()
        My.Settings.AudioDJErhain_UWBeats_Maniac = 0
        My.Settings.Save()
        My.Settings.AudioDjErhain_Misty = 0
        My.Settings.Save()
        My.Settings.AudioMachinimaSound_Exigence = 0
        My.Settings.Save()

        My.Computer.Audio.Play(My.Resources.Simplex_Memories_master, AudioPlayMode.BackgroundLoop)

    Else
    End If

Upvotes: 2

Views: 770

Answers (1)

Hans Passant
Hans Passant

Reputation: 941545

Yes, this is likely to go wrong, the .wav format is not very compact. When you put it in a resource then using the resource is going to create an UnmanagedMemoryStream. It should be disposed when you don't use it anymore, the garbage collector won't run often enough to keep you out of trouble.

Add a new Module to your project and paste this code:

Imports System.IO

Module PlayerUtilities

    Private CurrentStream As WeakReference(Of Stream)

    Public Sub PlayResource(wave As Stream)
        My.Computer.Audio.Play(wave, AudioPlayMode.BackgroundLoop)
        Dim oldwave As Stream = Nothing
        If CurrentStream IsNot Nothing AndAlso CurrentStream.TryGetTarget(oldwave) Then
            oldwave.Dispose()
        End If
        CurrentStream = New WeakReference(Of Stream)(wave)
    End Sub

End Module

And replace your calls to My.Computer.Audio.Play() with PlayResource(). The Dispose() call in this method on the previous audio stream will keep you out of trouble.

Upvotes: 1

Related Questions