Question Need to speed up loading MP3 File Info into ListView

Untamed

Well-known member
Joined
Jul 25, 2009
Messages
53
Programming Experience
5-10
Hello all. I am working on an advanced [at least I'd like to call it that] audio player. Currently, it supports .wmv and .mp3

It has the ability to recursively grab all .wmv and .mp3 files in any chosen folder, and add them to a playlist.

When opening the playlist, my program adds all the songs to an array, then starts adding the songs to a listview, categorizing them by song, artist, album, and genre, using a dll to access the ID3v1 tags on the .mp3 file.

It can successfully create playlists of thousands of songs at a somewhat okay speed, the problem is loading that into the categorized listview.

It used around 75% of my friend's CPU while loading his 5k+ song playlist into the listview, and it never finished after loading it in for a couple minutes (it auto updates as it loads, because it is done in a new thread.)

It never finished because his OS has a bug where, if the CPU usage is over 100% for more then a few mins, it BSOD's, but that's beside the point.

His CPU, by the way, is a quad core 2.33 GHZ processor.

The listview loads thousands of songs by using a lot of CPU [low amount of RAM, less then 40MB 99% of the time], and it does it slowly. Any help to lower the amount of CPU usage, and possibly in exchange, increase the RAM usage, as well as increasing the speed in general of loading the songs into the listview, is highly appreciated.

The main sub that loads it in [this sub is ran in a new thread]

VB.NET:
   Sub dosinglelist()
        Dim mdi = Nothing
        Try
            For doint = 0 To music.Count - 1
                Try
                    Dim MP3 As New UltraID3
                    mdi = music(doint)
                    MP3.Read(mdi)
                    songnamevar = MP3.ID3v1Tag.Title
                    albumvar = MP3.ID3v1Tag.Album
                    artistvar = MP3.ID3v1Tag.Artist
                    genrevar = MP3.ID3v1Tag.GenreName
                Catch
                End Try
                Try
                    If String.IsNullOrEmpty(songnamevar) = True Or String.IsNullOrWhiteSpace(songnamevar) = True Then
                        Dim tempmdi As String = ToName(mdi)
                        songnamevar = tempmdi.Substring(0, tempmdi.Length - 4)
                        If String.IsNullOrEmpty(songnamevar) = True Or String.IsNullOrWhiteSpace(songnamevar) = True Then
                            songnamevar = "N/A"
                        End If
                    End If
                    If String.IsNullOrEmpty(artistvar) = True Or String.IsNullOrWhiteSpace(artistvar) = True Then
                        artistvar = "N/A"
                    End If
                    If String.IsNullOrEmpty(albumvar) = True Or String.IsNullOrWhiteSpace(albumvar) = True Then
                        albumvar = "N/A"
                    End If
                    If String.IsNullOrEmpty(genrevar) = True Or String.IsNullOrWhiteSpace(genrevar) = True Then
                        genrevar = "N/A"
                    End If
                    Invoke(New ThreadStart(AddressOf dorowsinsert))

                Catch ex As Exception
                    songnamevar = "N/A"
                    albumvar = "N/A"
                    artistvar = "N/A"
                    genrevar = "N/A"
                    Invoke(New ThreadStart(AddressOf dorowsinsert))
                End Try
            Next doint
            listloading = False
        Catch ex As Exception
            MsgBox("Major error loading playlist visually! Will try again..." & Environment.NewLine & ex.ToString)
            dosinglelist()
        End Try
    End Sub
    Sub dorowsinsert()
        Dim str(3) As String
        Dim itm As ListViewItem
        str(0) = songnamevar
        str(1) = artistvar
        str(2) = albumvar
        str(3) = genrevar
        itm = New ListViewItem(str)
        SingleList.Items.Add(itm)
    End Sub

I've already redone the sub once or twice to speed it up, and at the moment it's 2-3x faster then it originally was, but it is still very cpu-heavy and quite slow, so any help on improving it is highly appreciated.

Thanks for the help guys!
 
5000 items eh? You should really consider providing only a filtered list, and if no filter is applied limit the list to say 100 items.

With the current setup the number one speed improvement will be to use Control.BeginInvoke instead of Control.Invoke, this will allow the background thread to continue processing mp3s without waiting for the UI to update each item. Use ParameterizedThreadStart delegate to pass info over instead of the single set of module variables (songnamevar etc).

Reading the tag info from each mp3 is what takes most time here, if you're planning on making this program anything useful you have to place the info gathered from mp3 files into persistant storage, like a file or db, this will save considerable time later when starting the program again, and later you only need to get info from new files for example. Anyway, you can't expect anything else than maxing cpu when doing processor intensive tasks, though you can lower the thread priority from default Normal.

I don't think calling 'dosinglelist' in Catch block is a good call, if the cause of the Exception is not resolved you have a never-ending-loop. At least you should ask user for confirmation, to enable opting out.
 
Back
Top