ForceStable/SetCell -> IDSC

Grafische Primitive, XbaseParts und Darstellungsfragen allgemein.

Moderator: Moderatoren

Antworten
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

ForceStable/SetCell -> IDSC

Beitrag von Tom »

Ich habe zwar wenig Hoffnung, dass mir hier jemand weiterhelfen kann, aber vielleicht unterschätze ich das Forum ja auch. :wink:

Ich arbeite viel mit Ownerdrawing. In Browses verwende ich abgeleitete Klassen, die u.a. die Methode CustomDrawCell() enthalten, aber auch einiges mehr. Die in den Methoden verwendeten Funktionalitäten sind vielfach abgesichert und tausendfach auf Herz und Nieren geprüft. Ich weiß inzwischen, was man darf und was nicht (z.B. auf Tabellen zugreifen oder im Ausgabekontext außerhalb des Presentation Spaces herumfrickeln), und ich gehe eigentlich davon aus, all das auch zu beherzigen. Dies umso mehr, da die Fehlersituation, mit der ich zuweilen zu tun habe, nur sehr selten auftreten, aber sie tun es. Leider.

Es geht um einen IDSC (Interne Datenstrukturen beschädigt), der im Kontext von XbpBrowse:ForceStable auftritt, und zwar dort im :SetCell() der DataArea. Die Argumente im Fehlerfall sind "XbpCellGroup" (die DataArea), ein numerischer Wert (die Ordinalposition der Zeile der DataArea) und überraschenderweise ein NIL, wo eigentlich der Wert enthalten sein sollte, der der Zelle per DataLink zugewiesen wurde. In meinen CustomDrawCell-Methoden und auch in den anderen überlagerten Methoden gibt es kein SetCell (aber einige GetCells, die allesamt funktionieren).

Nun dachte ich, ich bin ein ganz schlauer und überlagere einfach das ForceStable() mit einer eigenen Methode, wo ich dann den Aufruf des eigentlichen ForceStable in eine Sequenz einbette - in der Hoffnung, dass das Browse trotzdem angezeigt wird und irgendwo eine blanke Zelle zu sehen ist:

Code: Alles auswählen

METHOD MyBrowse:ForceStable()
LOCAL bSaveError := ErrorBlock({|e|Break(e)})
IF ::status() == XBP_STAT_CREATE
  BEGIN SEQUENCE
  ::XbpBrowse:ForceStable()
  END SEQUENCE
ENDIF
ErrorBlock(bSaveError)
RETURN self
Und, tatsächlich, jetzt bekomme ich keinen IDSC mehr, dafür aber einen App-Hang in XbpBrowse:ForceStable oder einen Freeze (kein Alt-C mehr möglich).

Kennt jemand diese Situation? Ich meine, sie muss nicht unbedingt mit Ownerdrawing zu tun haben. Es könnte sich auch um ein generelles (Timing?)Problem in XbpBrowse handeln.

1.9 SL1.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: ForceStable/SetCell -> IDSC

Beitrag von Tom »

Bin schon einen Schritt weiter. Roger Donnay hat mich auf die XbpBrowse-Sourcen hingewiesen. In denen habe ich tatsächlich die verursachende Zeile gefunden, in der es darum geht, in einem Browse, das nicht alle anzuzeigenden Zeilen mit Daten füllt (das Browse ist größer als die Datenmenge), die leeren Zellen anzuzeigen. Dort findet dann auch tatsächlich ein SetCell(<nRow>,NIL) statt, was ja auch funktionieren sollte. Warum es in dieser Situation gelegentlich einen IDSC auslöst, versuche ich morgen herauszufinden.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: ForceStable/SetCell -> IDSC

Beitrag von brandelh »

Ich hätte im obigen Code ein RECOVER USING oError Zweig erwartet, der den auftretenden Fehler logged.
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: ForceStable/SetCell -> IDSC

Beitrag von Tom »

Ich hätte im obigen Code ein RECOVER USING oError Zweig erwartet, der den auftretenden Fehler logged.
Täte nichts nutzen, ich bekomme ja keinen, sondern einen Hang oder Freeze.

Allerdings habe ich an der fraglichen Stelle soeben ein Logging vor den Aufruf von ::XbpBrowse:ForceStable() gesetzt, in dem ich die iVars protokolliere, die an der fehlerverursachenden Stelle im Quellcode von XbpBrowse verwendet werden. Mal schauen, was die mir erzählen.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: ForceStable/SetCell -> IDSC

Beitrag von Tom »

Falls es jemanden interessiert:

Die Lösung war dann doch vergleichsweise simpel. Ich habe in mein überlagertes ForceStable() einiges an Debugging-Code eingebaut, um herauszufinden, warum die im Orginalcode des XbpBrowse aufgerufene Makrofunktion "BRW_ClearRow(<nRow>)" manchmal zu einem IDSC, zuweilen aber auch zu einem Hang oder Freeze führt. Tatsächlich tat sie das im exakt gleichen Moment mit den exakt gleichen Daten mal nach zwanzig oder vierzig Aufrufen, mal gleich beim ersten. Das Debugging hat mir aber nicht direkt geholfen, denn alle relevanten Parameter waren richtig und immer ganz genau gleich. Ich habe den Code dann näher untersucht. Diese Makrofunktion wird in "AEval(self:aColumns,{|o|o:DataArea:SetCell(<nRow>,NIL)})" übersetzt. Sie wird aufgerufen, wenn ein Browse mehr Zeilen enthält als Daten angezeigt werden können - das Array hat 17 Zeilen, das Browse aber 20, also müssen 3 Zellen geleert werden. Dies geschieht im Stabilisierungszyklus. Dadurch, dass die Zelleninhalte geleert/genilt werden, wird ein (Re)Paint der Zellen ausgelöst, was in meinen abgeleiteten Klassen CustomDrawCell aufruft. Dort versuche ich zuerst, ein paar Präsentationsparameter auszulesen und z.B. die Anzeigefarbe der Zelle zu ermitteln, bevor ich prüfe, ob die Zelle selbst leer bzw. nil ist. Stelle ich das um, also prüfe ich erst, ob ich eine leere Zelle erhalte, um dann mit dem Rückgabewert .F. das Zeichnen durch die Standardroutinen auszulösen, bekomme ich keine Fehler mehr. Tatsächlich jedoch reflektiere ich in den fraglichen Systematiken (Codeblöcke für die Farben usw.) bereits diese Situation. Das ist merkwürdig. Und die Tatsache, dass es nicht immer gecrasht hat. So oder so, das Problem ist dadurch gelöst, dass ich in der Methode ganz am Anfang prüfe, ob die Zelle leer ist, und erst wenn das nicht der Fall ist weitere Untersuchungen vornehme. Puh.
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: ForceStable/SetCell -> IDSC

Beitrag von AUGE_OHR »

Tom hat geschrieben:Falls es jemanden interessiert:
Ja
Tom hat geschrieben: Dort versuche ich zuerst, ein paar Präsentationsparameter auszulesen und z.B. die Anzeigefarbe der Zelle zu ermitteln, bevor ich prüfe, ob die Zelle selbst leer bzw. nil ist.
also eine "Aktion" vorher
Tom hat geschrieben:Stelle ich das um, also prüfe ich erst, ob ich eine leere Zelle erhalte, um dann mit dem Rückgabewert .F. das Zeichnen durch die Standardroutinen auszulösen, bekomme ich keine Fehler mehr.
das ist interessant.
Tom hat geschrieben:So oder so, das Problem ist dadurch gelöst, dass ich in der Methode ganz am Anfang prüfe, ob die Zelle leer ist, und erst wenn das nicht der Fall ist weitere Untersuchungen vornehme.
wenn ich dich richtig verstehe sollten das als erstes nach den LOCAL kommen

Code: Alles auswählen

xData := oSelf:getCell( aRowCol[ 1 ], aRowCol[ 2 ] )
IF NIL = xData
   RETURN .T.
ENDIF
gruss by OHR
Jimmy
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: ForceStable/SetCell -> IDSC

Beitrag von Tom »

Hallo, Jimmy.
wenn ich dich richtig verstehe sollten das als erstes nach den LOCAL kommen
Ja, ganz offensichtlich. Das ist ein wenig irritierend, weil der restliche Code, der bei mir bislang vorher kam (Erhebung der PP, Farbermittlung) eigentlich auch reflektiert hat, dass die Zelle NIL enthalten kann. Leider endet eine XPPFATAL bei Fehlern, die in CustomDrawCell entstehen, meiner Erfahrung nach vorher; der Callstack scheint mir in dieser Situation nicht ganz vollständig zu sein. Jedenfalls ist das Problem durch diese Umstellung verschwunden. Es gab ja nicht nur IDSCs, sondern auch Hangs und Freezes. Möglicherweise liegt dem ein Timing-/Synchronisationsproblem des UI-Threads zugrunde. Egal - Hauptsache, es ist weg.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: ForceStable/SetCell -> IDSC

Beitrag von brandelh »

Wobei es von der Logik her sinnvoll ist durch die Abfrage nach NIL ganz am Anfang dem kompletten Rest zu überspringen, selbst wenn es keine Fehler gibt. :wink:
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: ForceStable/SetCell -> IDSC

Beitrag von Tom »

Man überspringt nicht den kompletten Rest, sondern beendet die Methode mit dem Rückgabewert .F., um das Zeichnen durch die internen Routinen auszulösen. Aber, ja, Hubert, Du hast prinzipiell Recht. Andererseits ist eben irritierend, dass die Ermittlung der Präsentationsparameter oder der Farbwerte ganz offenbar zur Fehlersituation führte, obwohl darin reflektiert wurde, dass der Zellenwert NIL sein konnte. Mehr noch, es erzeugte ja nur in einem von durchschnittlich dreißig Aufrufen (unter exakt gleichen Bedingungen) einen Fehler, was für mich ein klarer Hinweis darauf ist, dass es nicht am fraglichen Code - der bislang der Abfrage voranging - gelegen haben kann.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: ForceStable/SetCell -> IDSC

Beitrag von brandelh »

Hallo Tom,

auch du hast Recht, dass es eigentlich nicht am erlaubten Xbase++ Code liegen kann, denn dann müsste ein anderer Fehler in der normalen Fehlerbehandlung auftauchen.
Es ist eben ein "interner Fehler", den Xbase++ nicht abfangen kann und nach meiner Erinnerung hat einer von Alaska mal erwähnt, dass diese Fehler eigentlich "das Versagen" des Xbase++ Fehlersystem in diesem Fall dokumentierten. Ein hoher Anspruch, der von Menschen kaum gehalten werden kann. ;-)

Offensichtlich gibt es bei einem internen Zugriff den Fall, dass alle Stricke reißen ...
als kurzfristige Lösung bleibt da immer nur zu versuchen einen anderen internen Verarbeitungsweg zu erreichen. :D
Gruß
Hubert
Antworten