Dynamisch Variablen der Thread Klasse erzeugen

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

Moderator: Moderatoren

Antworten
notloesung
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 194
Registriert: Fr, 24. Feb 2006 8:09
Kontaktdaten:

Dynamisch Variablen der Thread Klasse erzeugen

Beitrag von notloesung »

Hallo,

ich erzeuge in meinem Programm zu Laufzeit dynamische Variablen der Thread Klasse.

Code: Alles auswählen

   MEMVAR ThreadVar

...

   ThreadVar := "Thread" + Alltrim( Str( DB->( RecNo() ) ) )
   IF ! IsMemvar( "&ThreadVar" )
      PUBLIC &ThreadVar
   ENDIF
Danach erzeuge ich den Thread (hier vereinfacht dargestellt).

Code: Alles auswählen

   IF Empty( &ThreadVar )
      &ThreadVar := myThread():new()
      ...
      &ThreadVar:atStart := {|| &ThreadVar:DBEInit() }
      &ThreadVar:atEnd   := {|| DbCloseArea() }
      &ThreadVar:setInterVal( 100 )
      &ThreadVar:start()
   ENDIF
Der Instanzvariablen atStart weise ich eine Methode meiner Thread Klasse zu.
Und da knallt es auch schon, denn ThreadVar ist eine unbekannte Variable sagt das Fehlerprotokoll. Mit ::DBEInit() lässt sich die Methode ebenfalls nicht ansprechen, da SELF eine unbekannte Variable ist.
Irgendwie ist es schon einleuchtend. Denn die Variable heißt ja auch zur Laufzeit nicht ThreadVar, sondern z.B. Thread4711 da,

Code: Alles auswählen

ThreadVar := "Thread" + Alltrim( Str( DB->( RecNo() ) ) ) )
Also müsste die Zeile dann heißen:

Code: Alles auswählen

   &ThreadVar:atStart := {|| Thread4711:DBEInit() }
Nur wo kriege ich jetzt den Namen der Variable her? Oder ist es einfach nur "einfach" und ich komme nicht drauf :?:
Oder bin ich mit meiner Denkweise falsch?
Wie kriege ich es hin an der Stelle eine Methode meiner Klasse aufzurufen?

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

Beitrag von Martin Altmann »

Hallo notloesung,
hast Du mal versucht, mit &( zu arbeiten?

Code: Alles auswählen

&ThreadVar:atStart := {|| &(ThreadVar):DBEInit() }
Abgesehen davon müßte doch eigentlich auch

Code: Alles auswählen

&ThreadVar:atStart := {|| ::DBEInit() }
funktionieren, oder nicht??

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.
notloesung
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 194
Registriert: Fr, 24. Feb 2006 8:09
Kontaktdaten:

Beitrag von notloesung »

Hi Martin,
&ThreadVar:atStart := {|| &(ThreadVar):DBEInit() }
erzeugt einen Syntaxfehler.

Und das
&ThreadVar:atStart := {|| ::DBEInit() }
was aus meiner Ansicht nach funktionieren sollte knallt zur Laufzeit.

Im Fehlerprotokoll steht:
oError:description : Unbekannte Variable
oError:operation : SELF
Es gibt ja die Methode :ClassName(). Im Prinzip suche ich also genau so etwas nur halt für 'ne Variable.

Gruß,
Notloesung
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hi,

bei meiner uralten Druckervariablen Steuerung weise ich auch einer PublicVar (deren Namen in einer anderen Variablen liegt) einen Wert zu.
Ich mußte damals einen Punkt nach dem Variablennamen setzen:

Code: Alles auswählen

statt        &ThreadVar:atStart := {|| &ThreadVar:DBEInit() } 
versuche    &ThreadVar[color=red].[/color]:atStart := {|| &ThreadVar[color=red].[/color]:DBEInit() } 
oder        &(ThreadVar):atStart := {|| &(ThreadVar):DBEInit() } 
Bei MEMVAR Variablen ist es sinnvoll diese mit MEMVAR zu deklarieren oder mit M-> anzusprechen, du deklarierst zwar die Variable, die den Namen der eigentlichen Variable enthält, aber nicht die Variable, die die eigentliche Arbeit macht. Vielleicht geht

ThreadVar := "M->Thread".... besser ???

Ich würde versuchen die Erstellung der NAMENxyz zu umgehen, indem ich alles in ein Array packen würde:

Code: Alles auswählen

aThread := {}
aadd( aThread, {oThread, nWorkArea, nRechno, ...})
so hättest du die Infos, die du bisher über die Satznummer etc. zusammensuchst in einer aScan tauglichen Form, geendete Threads müssen hier natürlich wieder aufräumen.

Grundsätzlich darf in einem CODEBLOCK kein Verweis auf SELF oder interne Methoden und InstanzVariablen stehen, da es ein externer Aufruf ist (Lokale Variablen bzw. EXPORTED gehen).

Auch ist es problematisch einen Codeblock so anzulegen, wenn die Variablen zur COMPILE-Zeit nicht sauber aufgelöst werden können:

bisher: ThreadVar:atStart := {|| &ThreadVar:DBEInit() } // der Compiler weiß nix ...

sicherer wäre es den Codeblock zur Laufzeit zu generieren, wobei dies absolut nötig ist, wenn die Variableninfo in einer local liegt:

variabler: ThreadVar:atStart := &("{||"+ThreadVar+":DBEInit() }")

da dies langsamer ist, sollte man es aber nur anwenden, wenn die Variablen nicht bekannt sind.
Gruß
Hubert
notloesung
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 194
Registriert: Fr, 24. Feb 2006 8:09
Kontaktdaten:

Beitrag von notloesung »

Hallo Hubert,

wenn ich die Variable mit M-> anspreche komme ich schon ein Schritt weiter. Es entsteht noch ein Laufzeitfehler aber im Fehlerprotokoll steht jetzt der "richtige" Variablenname. Zwar auch wieder als unbekannte Variable aber zumindest mit der richtigen Bezeichnung.
oError:description : Unbekannte Variable
oError:operation : Thread4711
Dennoch denke ich nach ob es nicht wirklich besser währe ein Array mit den Thread Objekten zu füttern.
Und da mir momentan keine Nachteile einfallen, werde ich das mal austesten :idea:

Schönen Gruß,
Notloesung
Antworten