Falscher Objektstatus

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
Benutzeravatar
Josef Stockinger
UDF-Programmierer
UDF-Programmierer
Beiträge: 53
Registriert: So, 25. Sep 2005 18:06
Wohnort: Nähe Regensburg
Kontaktdaten:

Falscher Objektstatus

Beitrag von Josef Stockinger »

Hallo alle, hier komm ich nicht weiter:

Aus dem Hauptdialog starte ich das Programm in einem eigenen Thread. Die Anzeige von selektierten Datenmengen mit folgender Funktion klappt einwandfrei, auch mehrfach. Die STATIC oBrowseX ist vor der App1_Main definiert.

Code: Alles auswählen

STATIC FUNCTION DbSatzBrowse( oBrowseX, oExport, aPickField, aParallel )
   LOCAL GetList := {}, i, aChildList := {}
[color=red]   IF Valtype(oBrowseX) = 'O'
      aChildList := oBrowseX:ChildList()
      FOR i := 1 TO Len(aChildList)
        aChildList[i]:Destroy()
      NEXT
      oBrowseX:Destroy()
   ENDIF
   oBrowseX := nil
[/color]   IF Empty(aPickField)
      RETURN nil
   ENDIF
   @ 0,0 DCBROWSE oBrowseX DATA aPickField SIZE 65,20 ;
     PARENT oExport  PRESENTATION  aBrowPres

   DCBROWSECOL DATA {|| DC_GetColArray(5, oBrowseX) };
     HEADER 'Konto' PARENT oBrowseX  WIDTH 6
   DCBROWSECOL DATA {|| DC_GetColArray(6, oBrowseX) };
     HEADER 'BLZ' PARENT oBrowseX  WIDTH 5
   DCBROWSECOL DATA {|| DC_GetColArray(7, oBrowseX) };
     HEADER 'Bank' PARENT oBrowseX  WIDTH 14
   DCBROWSECOL DATA {|| DC_GetColArray(8, oBrowseX) };
     HEADER 'Inhaber' PARENT oBrowseX  WIDTH 8

   DCREAD GUI ;
      PARENT oExport ;
      EXIT
   oBrowseX:hide()
   oBrowseX:show()
RETURN nil
Beende ich diesen Thread und starte dann wieder, kommt es zur Fehlermeldung:

Code: Alles auswählen

Xbase++ Version     : Xbase++ (R) Version 1.80.284
Betriebssystem      : Windows XP 05.01 Build 02600 Service Pack 2
------------------------------------------------------------------------------
oError:args         :
          -> VALTYPE: O CLASS: DC_XbpBrowse
oError:canDefault   : .F.
oError:canRetry     : .F.
oError:canSubstitute: .T.
oError:cargo        : NIL
oError:description  : Falscher Objekt Status
oError:filename     : 
oError:genCode      :        104
oError:operation    : :ChildList
oError:osCode       :          0
oError:severity     :          2
oError:subCode      :       4208
oError:subSystem    : BASE
oError:thread       :          3
oError:tries        :          0
------------------------------------------------------------------------------
CALLSTACK:
------------------------------------------------------------------------------
Aufgerufen von DBSATZBROWSE(2225)
Aufgerufen von SUBPROC(1038)
Aufgerufen von (B)APP1_MAIN(810)
SubProc() lautet:

Code: Alles auswählen

   // BrowseX aufbauen
   elseif nAktion = 5
        aParallel := DbSatzField(.f.)
        DbSatzBrowse( @oBrowseX, @oExport, @aPickField, aParallel )
        DbGoTop()
Code in App1_Main(810):

Code: Alles auswählen

   DCREAD GUI  ;
      EVAL {|o| SetAppWindow(oApp1Dlg), SubProc(5,aLocals), oApp1DlgWindow:Show(),oApp1DlgWindow:setTitle(cTitle) } ;
      HANDLER _DlgHandler REFERENCE oDialog  ;
      OPTIONS GetOptions  ;
      SETFOCUS @oTabPage1 ;
      PARENT @oDialog
Woran kann das liegen?
Wer kann mir dazu Tipps geben ?

Josef
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16511
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Josef,
Du destroyst die oBrowseX doch beim ersten Aufruf - danach gibt es das Objekt nicht mehr...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Josef Stockinger
UDF-Programmierer
UDF-Programmierer
Beiträge: 53
Registriert: So, 25. Sep 2005 18:06
Wohnort: Nähe Regensburg
Kontaktdaten:

Beitrag von Josef Stockinger »

Hallo Martin,

auch wenn ich oBrowseX:Destroy() rausnehme, bleibt es beim Fehler.

oBrowseX:Destroy(), dann oBrowseX:configure() bringt auch nichts.

Wenn ich APP1_Main (eigener Thread) beende, ohne die gesamte Applikation zu killen, und dann wieder starte, werden doch auch die vor der Main_Procedur definierten STATIC-Variablen - auch oBrowseX - wieder erzeugt !?.
Oder sind die auch noch nach Thread-Ende (ohne App-Ende) vorhanden? Kann wohl nicht sein.

Josef
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16511
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Josef,
Du übergibst das Objekt per Referenz und killst es in der Prozedur - also killst Du auch das Original außerhalb der Prozedur.
Darüber war ich gestolpert...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Falscher Objektstatus

Beitrag von brandelh »

Josef Stockinger hat geschrieben:

Code: Alles auswählen

STATIC FUNCTION DbSatzBrowse( oBrowseX, oExport, aPickField, aParallel )
    ...
   IF Valtype(oBrowseX) = 'O'
      ...
      oBrowseX:Destroy()
   ENDIF
[color=red]
   oBrowseX := nil   // das zerstört das Object oder den Zugriff darauf, aber nicht die Variable
  und damit kommt hier nur noch NIL an ...
[/color]...
   oBrowseX:hide()
   oBrowseX:show()
RETURN nil
Also soweit ich weiß bleiben STATIC solange vorhanden, wie das Programm läuft.
Gruß
Hubert
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: Falscher Objektstatus

Beitrag von AUGE_OHR »

hi,
brandelh hat geschrieben: Also soweit ich weiß bleiben STATIC solange vorhanden, wie das Programm läuft.
so steht es in den Help File :
Sichtbarkeit von Variablen in verschiedenen Threads

Sichtbarkeit Speicherklasse

Sichtbar im Prozeß PUBLIC
(alle Threads) STATIC

Sichtbar im Thread LOCAL
(ein Thread) PRIVATE
FIELD
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo,

noch was zum Thema STATIC Vars ...

Code: Alles auswählen

function Test(cNeuText)
   static cTest := "das erste Mal"
   if ! cNeuText = NIL
     cTest := cNeuText
   endif
return cTest

proc main
   ? test()          -> "das erste Mal"
   ? test("Neu")  -> "Neu"
   ? test()          -> "Neu"
return
Die Zuweisung hinter STATIC wird genau einmal aufgerufen, danach hängt der Inhalt vom letzten setzen ab. Gerade in Multithreading Programmen aber auch in GUI MDI Anwendungen vergessen alte Clipperprogrammierer oft, dass die Abarbeitungsreihenfolge immer unbestimmt ist.

Beim Test geht noch alles gut, aber ein Anwender ruft zwischendrinn ein anderes Fenster auf, dass diesen Wert verändert und wundert sich über die Nebenwirkungen.

STATIC und PUPBLIC dürfen nur verwendet werden, wenn nach der Initialisierung nur noch ein Lesezugriff auf den Inhalt erfolgen soll.

Z.B. speichere ich bei Hilfsfunktionen von Auswahlzeilen, welche immer gleich sind beim ersten Zugriff die DBF-Werte in einem STATIC-Array und liefere später nur noch Werte aus dem Array zurück.
Gruß
Hubert
Benutzeravatar
Josef Stockinger
UDF-Programmierer
UDF-Programmierer
Beiträge: 53
Registriert: So, 25. Sep 2005 18:06
Wohnort: Nähe Regensburg
Kontaktdaten:

Beitrag von Josef Stockinger »

Hallo Hubert und Manfred,

vielen Dank für die Tipps. Bezüglich STATIC habe ich dazu gelernt. oBrowseX war nach destroy() wirklich futsch und kommt erst wieder, wenn das gesamte Programm beendet und dann wieder gestartet wird. Beenden und wieder starten nur in dem Thread, wo die STATIC deklariert und verwendet wird, reichte nicht. Ich dachte, beim erneuten Aufruf des Thread sind auch alle dort definierten STATIC wieder verwendbar.

Das Problem habe ich nun anders gelöst. oBrowseX wird nun in der Main_PROC aufgebaut und veränderte Datenmengen per DC_Getbrowarray(oBrowseX, aArray) zur Anzeige gebracht. Das ist auch ein übersichtlicherer Aufbau.

Die Konstruktion hatte ich aus einem Beispiel von eXpress und war früher schon mal daran hängen geblieben. Aber da gabs diese Unterstützung vom Forum noch nicht.

Vielen Dank nochmals.
Josef
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hi,

zu Static muss ich ergänzen, dass je nach Ort der Initialisierung die STATIC Var entweder pro function/procedure oder aber für eine Quellcodedatei gilt. Mann kann also in 2 verschiedenen Quellcodedateien jeweils die gleiche STATIC definieren, was beim debuggen und der Fehlersuche sicher für helle Freude sorgt ;-)

Daraus folgt aber auch, dass beim normalen Projektaufbau mit verschiedenen PRGs die Static die Public nicht ersetzen kann. Ich nutze dafür Funktionen, die interne Statics verwenden oder aber iVars des Hauptfensters.
Gruß
Hubert
Antworten