![]() |
Delphi-Version: XE5
Ab und zu unerklärliche Fehler beim Laden von XML-Daten
Hallo,
ich habe zur Zeit ein recht nerviges Problem, welches ich euch hier mal kurz schildern möchte. Ich habe ein Programm, welches im OnShow-Event des Hauptformulars alle Werte verschiedener XML-Dateien laden soll. Das funktioniert manchmal wunderbar, manchmal kommen aber auch an ständig anderen Stellen verschiedene Fehler. Beispiele für Fehler:
Das sind zumindest mal die drei häufigsten Fehler. Wahrscheinlich kann man jetzt noch gar nicht helfen. Leider ist es mir nicht möglich/gestattet hier den kompletten Code zu posten. Dennoch hier der grobe Ablauf
Delphi-Quellcode:
procedure LoadObjects;
var threadID: DWord; begin CreateThread(nil, 0, TFNThreadStartRoutine(@LoadObjectsThreadFunc), nil, 0, threadId); end;
Delphi-Quellcode:
procedure LoadObjectsThreadFunc(p: pointer);
var si: TObjectUseType; sl: TStringList; err: string; begin CoInitialize(nil); WaitForSingleObject(g_LoadObjectsMutex, INFINITE); //CreateMutex wurde vorher aufgerufen sl := TStringList.Create; for si := Low(TObjectUseType) to High(TObjectUseType) do begin g_dataManager.getFiles(sl, ObjectFileType[si]); g_Objects[si].loadFromXMLFiles(sl,err); //DANACH FEHLER g_Objects[si].Sort(g_SortType); end; FreeAndNil(sl); ReleaseMutex(g_LoadObjectsMutex); end;
Delphi-Quellcode:
function TPersistentObjectList.LoadFromXMLFiles(const sl: TStringList; var err: string): boolean;
var FXMLDoc: TXMLDocument; FSaver: TXMLSaverBase; i: integer; FValue: TPersistent_; FNode: IXMLNode; begin err := ''; Result := true; Clear; try try FSaver := TXMLSaverBase.Create; if assigned(sl) then begin for i := 0 to sl.Count-1 do begin FXMLDoc := TXMLDocument.Create(Application); FXMLDoc.FileName := sl.Strings[i]; FXMLDoc.Active := true; FNode := FXMLDoc.DocumentElement; FSaver.Node := FNode; FValue := TPersistent_Class(GetClass(FSaver.GetStrAttribute(CXML_CLASSNAME,'',true))).Create; Result := FValue.loadFromXMLNode(FNode,err); //Fehler FValue.FileName := sl.Strings[i]; Add(FValue); FreeAndNil(FXMLDoc); end; end else Result := false; finally FreeAndNil(FSaver); end; except Result := false; end; end;
Delphi-Quellcode:
function TObjectXYZ.loadFromXMLNode(iNode: IXMLNode;
var err: string): boolean; var FSaver: TXMLSaverBase; FNode: IXMLNode; begin Result := true; inherited loadFromXMLNode(iNode,err); try try FSaver := TXMLSaverBase.Create; FSaver.Node := iNode; FIrgendwas := FSaver.GetDoubleAttribute(CXML_Irgendwas,0,true); //manchmal bleibt er hier stehen FWasAnderes := FSaver.GetBoolAttribute(CXML_WasAnderes,false,true); //manchmal auch hier {...} finally FreeAndNil(FSaver); end; except on E: Exception do begin err := E.Message; Result := false; end; end; end;
Delphi-Quellcode:
function TXMLSaverBase.GetDoubleAttribute(const AttributeName: string; DefaultValue: Double; SendException: boolean): Double;
begin Result := StrToFloat_(GetAttribute(AttributeName, FloatToStr_(DefaultValue), SendException)); end;
Delphi-Quellcode:
Der Call-Stack sieht auch jedes mal etwas anders aus. Es hängt auch irgendwie damit zusammen, wann ich die XML-Dateien lade. Wenn ich sie z.B. beim Klick auf einen Button lade treten noch ganz andere Fehler auf. Zum Beispiel "zu wenig Arbeitsspeicher" (sind 8GB vorhanden und nie ansatzweise voll).
function TXMLSaverBase.GetAttribute(const AttributeName: string; DefaultValue: OleVariant; SendException: boolean): OleVariant;
function DoDefault(SendException: boolean): OleVariant; begin if SendException then raise EXMLReadException.Create(' GetAttribute: Node: ' + FNode.NodeName) else Result := DefaultValue; end; begin FLastReadError := emptystr; Result := 0; try if Assigned(FNode) then begin if(HasAttribute(AttributeName)) then Result := FNode.Attributes[AttributeName] else Result := DoDefault(SendException); end else begin Result := DoDefault(SendException); end; except Result := DoDefault(SendException); end; end; Ich kann mir vorstellen, dass man da wohl nur schwer von außen helfen kann aber vllt hat ja doch jemand eine Idee. Vllt auch ein paar Tipps, wie ich vorgehen kann, um den Fehler einzugrenzen. Hintergrund: Ich muss ein großes Delphi-Projekt von Delphi 7 auf XE5 umstellen und verwende dabei einige Units (wie z.B. XMLSaverBase) des alten Projektes um einigermaßen kompatibel zu bleiben. Die Fehler treten ja wie gesagt auch nur bei jedem 7ten Start oder so auf. Vielen Dank für eure Mühe. Grüße Headbucket |
AW: Ab und zu unerklärliche Fehler beim Laden von XML-Daten
Ohne wirklich eine konkrete Idee zu haben würde ich als erstes schauen, ob der Aufruf von
Delphi-Quellcode:
auch wirklich immer klappt. Ob da weiterhin im Zusammenhang mit COM reinspielt, dass du deinen Thread direkt über die WinAPI aufmachst weiß ich nicht, könnte doch vielleicht auch sein?
CoInitialize(..)
// Übrigens: Warum erstellst du ein TXMLDocument, explizit mit Application als Eigentümer-Komponente, gibst es aber selbst ein paar Zeilen später doch gewaltsam frei? Da würde ich auf IXMLDocument als Referenz-Typ umsteigen. Einladen dann mit
Delphi-Quellcode:
.
Xml.XMLDoc.LoadXMLDocument(const Filename: String)
|
AW: Ab und zu unerklärliche Fehler beim Laden von XML-Daten
Vielen dank für deine Antwort.
Zitat:
Zitat:
Zitat:
Ich habe aber auch schonmal versucht an der ein oder anderen Stelle ein Interface zu benutzen - bisher aber auch ohne Erfolg. Habe soeben auch nochmal mein XE5 auf den neusten Stand gebracht - hat aber auch nicht geholfen. Schwierig :-/ Eine Idee, wie ich mich da Schritt für Schritt rantasten könnte? Es ist halt schwierig, da die Fehler unterschiedlich sind und an unterschiedlichen Stellen auftauchen. /////Edit///// Ich habe soeben mal das ganze Mutex/Thread-Gedöns weggelassen und siehe da: Es funktioniert. Zumindest konnte ich dem Programm nach 50 mal starten keinen Fehler entlocken. Von der Theorie her sollte das ganze jedoch schon in einen Thread gepackt werden, da sehr viele Datensätze gelesen werden sollen und somit verhindert werden soll, dass jemand anders während des Ladens auf die Daten zugreift. Aber das Problem lässt sich sicher lösen und ist mir deutlich lieber als ein Problem mit der XML-Verarbeitung. Wie ich bisher vorgegangen bin: (1) CreateMutex im Initialization-Abschnitt (2) CreateThread und damit Aufruf der Procedure zum Laden (3) CoInitialize -> WaitForSingleObject -> Laden -> ReleaseMutex (4) CloseHandle im Finalization-Abschnitt Das ganze habe ich auch schon etwas abgewandelt - jedoch ohne Erfolg. Ich werd nochmal etwas Suchen und rumprobieren. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:02 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