![]() |
AW: Mp3FileUtils
Ich bin zwar nicht Gausi, aber das klingt danach, als ob Du immer wieder Objekte erzeugst, ohne sie anschließend freizugeben. Wie sieht denn Dein Code aus?
|
AW: Mp3FileUtils
DeddyH könnte da gut recht haben, danach hört es sich an. Benutzt du evtl. FastMM mit den Einstellungen zum Debuggen auf aktiv? Solche Effekte bekomme ich damit nämlich zustande, auch wenn ich alles Freigebe. Hast du es mal mit ReportMemoryLeaksOnShutdown probiert? Damit würdest du eventuelle Leaks vermutlich schnell finden.
|
AW: Mp3FileUtils
Hier ist mein Code:
Delphi-Quellcode:
in meiner haupunit habe ich dann unter private ein TMainConfig-Objekt deklariert(ProConfig). Beim Programmstart werden die StringListen erstelt uns aus Dateien geladen.
//Typendeklaration für Bibliothek
type TLibrary=record Files :TStringList;//Damit ordne ich den Titelinfos die pfade zu Cols:Array[1..3] of TStringList;//Col[1] für Titel, Col[2] für Interpret, Col[3] für Spiellänge //... end; type TMainConfig=record Lib:TLibrary; //... end; //Typendeklaration für Titelinformationen type TAudioInf=record; Interpret: string; Titel : string; Pfad : string; Album : string; Jahr : string; Dauer : integer; end; //Unit mit Prozeduren zum Auslesen der Infos (aus dem Delphitreff) unit UAudioInf; interface uses UTypes; procedure GetAudioInfo(FileName: string); procedure GetMp3Info; procedure GetWmaInfo; procedure SetUnknown; function GetPlaylistTitel:string; var AudioInf: TAudioInf; implementation uses SysUtils, Mp3FileUtils, ATL_WMAfile, Classes; //Hauptprozedur für Titelinformationen procedure GetAudioInfo(FileName: string); begin AudioInf.Pfad := filename; if (AnsiLowerCase(ExtractFileExt(FileName)) = '.mp3') then GetMp3Info else if AnsiLowerCase(ExtractFileExt(FileName)) = '.wma' then GetWMAInfo else SetUnknown; if AudioInf.Interpret='' then AudioInf.Interpret:='Unbekannter Interpret'; if AudioInf.Album='' then AudioInf.Album:='Unbekanntes Album'; if AudioInf.Jahr='' then AudioInf.Jahr:='unbekanntes Jahr'; end; //Prozedur für Titelinformationen von MP3-Dateien procedure GetMp3Info; var MpegInfo: TMpegInfo; ID3v2Tag: TID3V2Tag; ID3v1tag: TID3v1Tag; Stream: TFileStream; begin // Daten mit MP3FileUtils auslesen Mpeginfo:=TMpegInfo.Create; ID3v2Tag:=TID3V2Tag.Create; ID3v1tag:=TID3v1Tag.Create; Stream := TFileStream.Create(AudioInf.Pfad, fmOpenRead or fmShareDenyWrite); try id3v1tag.ReadFromStream(Stream); Stream.Seek(0, sobeginning); Id3v2tag.ReadFromStream(Stream); if Not id3v2Tag.exists then Stream.Seek(0, sobeginning) else Stream.Seek(id3v2tag.size, soFromBeginning); Mpeginfo.LoadFromStream(Stream); Stream.free; //Daten übertragen if mpeginfo.FirstHeaderPosition >- 1 then begin if id3v2tag.artist <> '' then AudioInf.Interpret := id3v2tag.artist else AudioInf.Interpret := id3v1tag.artist; if id3v2tag.Album <> '' then AudioInf.Album :=id3v2tag.Album else AudioInf.Album:=id3v1tag.Album; if id3v2tag.Year<> '' then AudioInf.Jahr:=id3v2tag.Year else AudioInf.Jahr:=id3v1tag.Year; if id3v2tag.title <> '' then AudioInf.Titel := id3v2tag.title else if id3v1tag.title <> '' then AudioInf.Titel := id3v1tag.title else AudioInf.Titel := ExtractFileName(AudioInf.Pfad); AudioInf.Dauer := mpeginfo.dauer; end else SetUnknown; finally MpegInfo.Free; Id3v2Tag.Free; Id3v1Tag.Free; end; end; //Prozedur für Titelinformationen von WMA-Dateien procedure GetWmaInfo; var wmaFile: TWMAfile; begin if Not FileExists(AudioInf.Pfad) then begin SetUnknown; exit; end; try wmaFile := TWMAFile.create; if wmaFile.ReadFromFile(AudioInf.Pfad) then begin if wmaFile.Title <> '' then AudioInf.Titel := wmaFile.Title else AudioInf.Titel := ExtractFilename(AudioInf.Pfad); AudioInf.Interpret := wmaFile.Artist; AudioInf.Dauer := Round(wmaFile.Duration); AudioInf.Album :=wmaFile.Album; AudioInf.Jahr :=wmaFile.Year; end else SetUnknown; finally wmaFile.Free; end; end; //Prozedur für Titelinformationen von unbekannten Dateien procedure SetUnknown; begin AudioInf.Titel := ExtractFileName(AudioInf.Pfad); AudioInf.Interpret := ''; AudioInf.Dauer := 0; end; //Prozedur für Titelinformationen nach %Interpret%-%Titel% function GetPlaylistTitel:string; begin if Trim(AudioInf.Interpret)='' then result := AudioInf.Titel else result := AudioInf.Interpret + ' - ' + AudioInf.Titel; end; Bei dieser Prozedur steigt dann der Speicherbedarf enorm an:
Delphi-Quellcode:
Wenn ich der Prozedur true übergebe zeigt sie mir eine kleine form, die den status anzeigt, aber auch wenn ich das ganze im hintergrund machen lasse (false übergeben) steigt der bedarf.
//Titelinformationen aktualisieren
procedure TForm1.LibRefreshInf(const Visualize: boolean); var i, a, b: integer; Edited: boolean; begin Edited:=false; if Visualize then begin Application.CreateForm(TFrmMakeUp, FrmMakeUp); FrmMakeUp.Show; FrmMakeUp.ChangesDone:=false; end; if ProConfig.Lib.Files.Count>0 then begin if Visualize then begin FrmMakeUp.ProgressBar1.Max:=ProConfig.Lib.Files.Count; FrmMakeUp.ProgressBar1.Position:=0; end; a:=0; for i:=ProConfig.Lib.Files.Count-1 downto 0 do begin if Visualize then begin inc(a); FrmMakeUp.ProgressBar1.Position:=a; FrmMakeUp.MainFile:=ProConfig.Lib.Files[i]; end else Application.ProcessMessages; if FileExists(ProConfig.Lib.Files[i]) then begin GetAudioInfo(ProConfig.Lib.Files[i]); if AudioInf.Titel<>ProConfig.Lib.Cols[1][i] then begin Edited:=true; ProConfig.Lib.Cols[1][i]:=AudioInf.Titel; end; if AudioInf.Interpret<>ProConfig.Lib.Cols[2][i] then begin Edited:=true; ProConfig.Lib.Cols[2][i]:=AudioInf.Interpret; end; if MsToMinuteSecond(AudioInf.Dauer*1000)<>ProConfig.Lib.Cols[3][i] then //MsToMinuteSecond wandelt begin //Sekunden in Minute:Sekunde um Edited:=true; ProConfig.Lib.Cols[3][i]:=MsToMinuteSecond(AudioInf.Dauer*1000); end; end; if not FileExists(ProConfig.Lib.Files[i]) then begin ProConfig.Lib.Files.Delete(i); for b:=1 to 3 do ProConfig.Lib.Cols[b].Delete(i); end; end; end; if Visualize then begin FrmMakeUp.ChangesDone:=true; FrmMakeUp.Close; end; end; EDIT:Ich habe gerade einen sehr eigenartigen Effekt festgestellt: Wenn ich in der Bibliothek meines Player 224 Elemente habe(Count der Stringlisten=224, Bedarf beim Start~1,8MB) dann steigt der Bedarf der Anwendung beim ausführen der Prozedur LibRefreshInf nicht. Wenn es aber 1014 Titel sind(Bedraf bei Start ~2,5 MB), dann steigt auf auf 182 MB. ??? |
AW: Mp3FileUtils
Also ich würde als erste dem Code ein Refactoring unterwerfen. So, wie ich das sehen kann, scheint alles in der Unit des Formulares zu stecken. Dazu kommen anscheinend noch globale Variablen und globale Datenstrukturen, weil du da noch einfache Prozeduren und Funktionen hast, die nicht Methoden deiner Klasse sind. Ich würde das erst mal alles sauber in eine oder eventuell sogar mehrere Klassen kapseln und so die GUI von der Datenverarbeitung trennen. Das hilft später bei der Erweiterung, der Überarbeitung und auch jetzt beim Finden von Fehlern und Speicherlecks. Eventuell verschwindet er ja schon beim Refactoring, wenn du wieder mehr Übersicht über deinen Code hast. Weil das ist doch nicht alles oder wird nicht alles bleiben oder?
|
AW: Mp3FileUtils
Nein, das ist nicht alles. Die Prozeduren zum Auslesen der Infos habe ich in eine eigene Klasse gepckt. Sie waren schon vorher in einer eigenen Unit. Aber es hat nichts geändert.
|
AW: Mp3FileUtils
Wird Action im OnClose von FrmMakeUp auf caFree gestellt?
|
AW: Mp3FileUtils
Ja, das ist so. Und er zeigt mir die Form ja auch nur an, wenn ich der Prozedur true übergebe. Wenn ich false übergebe, steigt der Speicherbedarf auch.
|
AW: Mp3FileUtils
Wird noch an anderer Stelle dynamisch Speicher angefordert?
|
AW: Mp3FileUtils
Ich habe in dem Programm einige andere kleine Formen, aber ich erstelle alle mit Application.CreateForm und bei OnClose ist Action überall auf caFree. Den record TAudioInf habe ich in eine Klasse umgeschrieben und die Prozeduren GetAudioInfo... dareingepackt. Ich habe dann in der Prozedur ein TAudioInf deklariert, es erstellt und gebe es mit try...finally und Free wieder frei.
|
AW: Mp3FileUtils
Dann würde ich gern mal die Klasse TAudioInf sehen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:18 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz