Thread und dbf [Erledigt]
Moderator: Moderatoren
- Jan
- Marvin
- Beiträge: 14658
- Registriert: Fr, 23. Sep 2005 18:23
- Wohnort: 49328 Melle
- Hat sich bedankt: 21 Mal
- Danksagung erhalten: 88 Mal
- Kontaktdaten:
Thread und dbf [Erledigt]
Kann jemand mir erklären, wie ich in einem anderen als dem aktuellen Thread alle dbf schließen, das Verzeichnis wechseln, und andere dbf neu öffnen kann?
Jan
Jan
Zuletzt geändert von Jan am Di, 08. Sep 2009 6:53, insgesamt 1-mal geändert.
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
- AUGE_OHR
- Marvin
- Beiträge: 12909
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 46 Mal
Re: Thread und dbf
theoretisch ...Jan hat geschrieben:Kann jemand mir erklären, wie ich in einem anderen als dem aktuellen Thread alle dbf schließen, das Verzeichnis wechseln, und andere dbf neu öffnen kann?
jeder Thread hätte ja seine WorkSpaceList()
eine WorkSpaceList() könnte man in den DB_ZEROSPACE legen
mit DbRequest() könnte man den Aliasnamen aus dem Zerospace in den aktuellen Workspace übertragen
mit DbRelease() könnte man den Aliasnamen aus dem aktuellen Workspace in den Zerospace übertragen
mit DbJob() könnte man den Workarea-Codeblock abfragen
und wenn man die ganzen "könnte" zu einem Puzzle zusammen bekommt, dann "könnte" es theoretisch funktionieren
ich habe sowass noch nicht "gebaut" und wüsste gerne für welchen Zweck du das vorhast ? anderen "Mandanten" ?
würde ich "so" nicht tun. ich habe immer einen Kompletten Path zur Dbf / Index.Jan hat geschrieben:Verzeichnis wechseln
Wenn ich den Mandanten Wechsel, dann den Path zur DBF, aber nicht das Applications Verzeichniss das könnte "ungünstig" sein.
was nun das "kommunizieren" von Threads angeht : ich verwenden USER_DEF Events und den 4th Parameter nTimeout in AppEvent.
wenn ich "einem" Thread einen Event senden will : PostAppEvent(myDEF,mp1,mp2,oThreadNo)
bei xbe_None = "Timeout" fragt jeder Thread den "Main-Stack" ab, welches ein n-Dim Array ist,
ob für "ihn" eine Msg (=Event) vorhanden ist.
der "Main Stack" ist ein separates PRG mit 2 "Fieldwide" STATIC für das n-Dim Array.
per "#define xtranslate =>" übersetze ich die Element des Arrays (leicht erweiterbar)
und zur identifizierung der n-Dim nutze ich :getHWND() (oder ThreadID aus ThreadInfo() )
Durch Functionen greife ich nun "von aussen" auf das n-Dim Array zu, wobei ohne Parameter = "get" und mit Parameter = "set"
Code: Alles auswählen
// "m"+ DBF FieldName
#xtranslate mARTIST => Stack\[SP,1]
#xtranslate mW9VIDEO => Stack\[SP,2]
...
// sonstige
#xtranslate aEditControls => Stack\[SP,17]
#xtranslate hWndEdit => Stack\[SP,18]
STATIC Stack := {}
STATIC SP := 0
FUNCTION EDIT_INIT()
AADD(Stack,ARRAY(18))
SP ++
// vorbelegen
EDIT_LEER()
RETURN (SP) // return nThread
PROCEDURE EDIT_EXIT(nThread)
LOCAL iMax
ADEL(Stack,nThread)
DO WHILE .T.
iMax := LEN(Stack)
IF iMax = 0
EXIT
ELSEIF Stack[iMax] = NIL
ASIZE(Stack,LEN(Stack) - 1)
ELSE
EXIT
ENDIF
ENDDO
SP := LEN(Stack)
RETURN
STATIC PROCEDURE EDIT_LEER()
mARTIST := " "
...
aEditControls := {}
hWndEdit := 0
RETURN
PROCEDURE EDIT_STORE(nRecno,nThread)
FIELD ARTIST // use FIELD ... while no Alias
...
IF PCOUNT() = 2
// switch to n-Dim
SP := nThread
mEditRec := nRecno
// STORE Data from DBF into Array
mARTIST := ARTIST
...
aEditControls := EditControls
ELSE
ENDIF
RETURN
STATIC PROCEDURE ST_REPLACE(nThread)
FIELD ARTIST // use FIELD ... while no Alias
...
// lese SLE in mVARs ein
// passiert durch :datalink
SP := nThread
GOTO(mEditRec)
* REF2GETS(aEditcontrols)
Gather(aEditcontrols)
IF (DBRLOCK(mEditRec))
FIELD->ARTIST := mARTIST
...
(DBRUNLOCK(mEditRec))
SP_LEDIT(.T.)
ELSE
MSGBOX("RLock fail")
ENDIF
RETURN
FUNCTION WM9EDIT(oParent,nThread,oBrowBrow)
...
oDlg := NewForm():new(AppDeskTop(),oParent,aPos,aSize,,.F.)
...
oDlg:cargo := nThread // Store Thread ID into :Cargo
oDlg:create()
AADD(aControls,oDlg)
hWndEdit := oDlg:getHWND()
...
oArtist := XbpSLE():new(oXbp1,,{84,216},{132,24},;
{{XBP_PP_BGCLR,XBPSYSCLR_ENTRYFIELD}})
oArtist:bufferLength := 30
oArtist:tabStop := .T.
oArtist:dataLink := VAR2BLOCK(@mARTIST)
oArtist:create():setData()
AADD(aEditControls,oArtist)
...
RETURN
FUNCTION SP_ARTIST(cValue) // can be called from "outside"
IF PCOUNT() > 0
mARTIST := cValue
ENDIF
RETURN (mARTIST)
gruss by OHR
Jimmy
Jimmy
- Jan
- Marvin
- Beiträge: 14658
- Registriert: Fr, 23. Sep 2005 18:23
- Wohnort: 49328 Melle
- Hat sich bedankt: 21 Mal
- Danksagung erhalten: 88 Mal
- Kontaktdaten:
Re: Thread und dbf
Hallo Jimmy,
Danke für die ausführliche Antwort. Da muß ich mich erstmal durcharbeiten.
Aber um ein paar Deiner Fragen zu beantworten: Ja, es geht um Mandanten. Jeder Mandant hat sein eigenes Verzeichnis, das die kompletten Datenbanken enthält. Dieses Verzeichnis wird über "Set Default To" zum Daten-Standardverzeichnis erklärt.
Da meine Projekte immer in viele Threads unterteilt sind wird auch ein Import-Modul in einem extra Thread gestartet. Hierbei besteht die Möglichkeit, die neuen Daten dem aktuell geöffneten Mandanten hinzuzufügen (dann habe ich natürlich keinerlei Probleme), oder ob die in einen neu zu erzeugenden eingelesen werden. Und da liegt die Schwierigkeit. Wenn ich die in einen neuen Mandanten einlese: Wie aktualisiere ich alle anderen Threads (wobei es hauptsächlich nur um einen fest definierten geht) mit diesem neuen Mandanten mit seinem Datenverzeichnis?
Jan
Danke für die ausführliche Antwort. Da muß ich mich erstmal durcharbeiten.
Aber um ein paar Deiner Fragen zu beantworten: Ja, es geht um Mandanten. Jeder Mandant hat sein eigenes Verzeichnis, das die kompletten Datenbanken enthält. Dieses Verzeichnis wird über "Set Default To" zum Daten-Standardverzeichnis erklärt.
Da meine Projekte immer in viele Threads unterteilt sind wird auch ein Import-Modul in einem extra Thread gestartet. Hierbei besteht die Möglichkeit, die neuen Daten dem aktuell geöffneten Mandanten hinzuzufügen (dann habe ich natürlich keinerlei Probleme), oder ob die in einen neu zu erzeugenden eingelesen werden. Und da liegt die Schwierigkeit. Wenn ich die in einen neuen Mandanten einlese: Wie aktualisiere ich alle anderen Threads (wobei es hauptsächlich nur um einen fest definierten geht) mit diesem neuen Mandanten mit seinem Datenverzeichnis?
Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
- AUGE_OHR
- Marvin
- Beiträge: 12909
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 46 Mal
Re: Thread und dbf
das ist einer der Gründe warum ich sage "voller" Path, den wie willst du "das" für 2 oder mehr Mandanten gleichzeitig machen ?Jan hat geschrieben:Dieses Verzeichnis wird über "Set Default To" zum Daten-Standardverzeichnis erklärt.
siehe doch jeden Thread als ein Array an und mehrere Threads als n-Dim Array dann bist du praktisch bei meinem Vorschlag.Jan hat geschrieben:Wenn ich die in einen neuen Mandanten einlese: Wie aktualisiere ich alle anderen Threads (wobei es hauptsächlich nur um einen fest definierten geht) mit diesem neuen Mandanten mit seinem Datenverzeichnis?
das #xtranslate hilft dir dabei dich in einem Thread = Array Ebene zu bewegen als wenn du nur einen Thread hättest,
aber du kannst auch ein AEVAL() (oder FOR/NEXT) über "alle Threads" machen wenn du die Objecte in ein Array übernimmst.
die ThreadID (bekommst du mit ThreadInfo() ) ist ja "eindeutig" z.b. für ein ASCAN() zum identifizieren welche Array Ebene gemeint ist.
vergessen hatte ich nun die NET_USE() der 2 Parameter hat : DBFname, nThreadID (= Mandant)
wobei "passend" zur DBF in der NET_USE() auch gleich die Index Datei(en) geöffnet werden.
Code: Alles auswählen
PROCEDURE NET_USE(DBFname, nThreadID)
...
nPosi := ASCAN(Sp_AllThread(),{|x| x[myThreadID] = nThreadID } )
IF nPosi > 0
// damit schalte ich auf die entsprechende Array Ebene = Thread
SP_Dim(nPosi)
// alles im Netz SHARED
DO CASE
CASE DBFname = "BlaBla"
USE (Sp_Mandant()+DBFname+".DBF") ALIAS DBFname VIA ... SHARED
SET INDEX TO Sp_Mandant()+x1,Sp_Mandant()+x2,Sp_Mandant()+x3
gruss by OHR
Jimmy
Jimmy
- Manfred
- Foren-Administrator
- Beiträge: 21200
- Registriert: Di, 29. Nov 2005 16:58
- Wohnort: Kreis Wesel
- Hat sich bedankt: 210 Mal
- Danksagung erhalten: 67 Mal
Re: Thread und dbf
Hi Jan,
jetzt kommt wieder das leidige Thema: mache Klassen und bilde Instanzen.
Jede Instanz weiß auf welche Datenbank sie wann und wo zugreifen muß. Da ist es Wurscht, welchen Thread du benutzt. Vergebe für jede Instanz einen evtl. anderen Pfad und schon paßt es. Ich habe nichts mit Default Pfad für Datenbanken usw.
jetzt kommt wieder das leidige Thema: mache Klassen und bilde Instanzen.
Jede Instanz weiß auf welche Datenbank sie wann und wo zugreifen muß. Da ist es Wurscht, welchen Thread du benutzt. Vergebe für jede Instanz einen evtl. anderen Pfad und schon paßt es. Ich habe nichts mit Default Pfad für Datenbanken usw.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
- Jan
- Marvin
- Beiträge: 14658
- Registriert: Fr, 23. Sep 2005 18:23
- Wohnort: 49328 Melle
- Hat sich bedankt: 21 Mal
- Danksagung erhalten: 88 Mal
- Kontaktdaten:
Re: Thread und dbf
Hallo Ihr beiden,
erstmal Manfred: Dein Vorschlag mag die Lösung sein. Aber Du kennst mich und die Klassen - zwei Welten prallen aufeinander. Das wird zumindest kurzfristig nichts werden. Außer Du schreibst mir das "mal eben" .
Jimmy: Ich kann mit Set Default To arbeiten, weil immer nur ein einziger Mandant geöffnet ist. Immer. Und wenn ich wechsle (es gibt einen Menüpunkt, über den man das über den XbpFileDialog machen kann), so mache ich das, indem ich den Pfad ändere und als Default setze. Und ansonsten, wie gesagt, ich werde mir Dein Beispiel näher ansehen. Das mit dem Array ist eine interessante Idee. Allerdings ist der Thread, in dem ich die dbf ändern muß, immer der gleiche. Ich brauche nicht danach zu suchen. Und ansonsten kann ich mir das ab SL1 auch einfacher machen, da ich einem Thread ja einen eindeutigen Nnamen geben kann, den ich dann direkt ansprechen kann.
Jan
erstmal Manfred: Dein Vorschlag mag die Lösung sein. Aber Du kennst mich und die Klassen - zwei Welten prallen aufeinander. Das wird zumindest kurzfristig nichts werden. Außer Du schreibst mir das "mal eben" .
Jimmy: Ich kann mit Set Default To arbeiten, weil immer nur ein einziger Mandant geöffnet ist. Immer. Und wenn ich wechsle (es gibt einen Menüpunkt, über den man das über den XbpFileDialog machen kann), so mache ich das, indem ich den Pfad ändere und als Default setze. Und ansonsten, wie gesagt, ich werde mir Dein Beispiel näher ansehen. Das mit dem Array ist eine interessante Idee. Allerdings ist der Thread, in dem ich die dbf ändern muß, immer der gleiche. Ich brauche nicht danach zu suchen. Und ansonsten kann ich mir das ab SL1 auch einfacher machen, da ich einem Thread ja einen eindeutigen Nnamen geben kann, den ich dann direkt ansprechen kann.
Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
- AUGE_OHR
- Marvin
- Beiträge: 12909
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 46 Mal
Re: Thread und dbf
hi,
@Manfred : ja man könnte es auch als Class ansehen und die beiden STATIC wären dann CLASS Var
Es ist nur so das man eine Class ja erst create()n muss bevor man sie "benutzen" kann und je
nach Code wäre das "ein Problem" alles umzustellen.
durch das n-Dim und die "eindeutige" ThreadID "sollte" es auch unter MDI keine Probleme machen.
es ist also für "alte" SDI Anwendungen (Cl*pper), die MemVars benutzen, per #define xtranslate
möglich daraus MDI Anwendungen zu machen ohne den "alten" Code komplett zu ändern.
deshalb auch die Procedure Namen : _STORE, _REPLACE, _LEER die noch aus dBase ][ Zeiten stammen.
@Jan
angenommen man hat seine Application in DLL aufgeteilt und in jeder DLL sind Threads.
Wie soll DLL No.1 das Thread Object aus DLL No2. "kennen" ?
so wie der Formdesigen bei XbpSLE ja ein AADD(editcontrol, oXbp) ausführt um die SLE in ein
Array aufzunehmen, so in der Art nehme ich auch alle "anderen Objecte" in solche Arrays auf.
... angenommen die Application läuft im Netzwerk. Die Daten sind auf dem Server und die Application wird local gestartet.
So nun ist der Server aber gar nicht physikalisch "vor Ort" sondern eine Remote "Freigabe" eines anderen PC.
mit einem "vollen" Path bekomme ich den Zugriff auf die DBF / Index Dateien, aber IMHO ein
@Manfred : ja man könnte es auch als Class ansehen und die beiden STATIC wären dann CLASS Var
Es ist nur so das man eine Class ja erst create()n muss bevor man sie "benutzen" kann und je
nach Code wäre das "ein Problem" alles umzustellen.
durch das n-Dim und die "eindeutige" ThreadID "sollte" es auch unter MDI keine Probleme machen.
es ist also für "alte" SDI Anwendungen (Cl*pper), die MemVars benutzen, per #define xtranslate
möglich daraus MDI Anwendungen zu machen ohne den "alten" Code komplett zu ändern.
deshalb auch die Procedure Namen : _STORE, _REPLACE, _LEER die noch aus dBase ][ Zeiten stammen.
@Jan
ja ... wenn du den "erreichst" mit einem PostappEvent() ist es ok.da ich einem Thread ja einen eindeutigen Namen geben kann, den ich dann direkt ansprechen kann.
angenommen man hat seine Application in DLL aufgeteilt und in jeder DLL sind Threads.
Wie soll DLL No.1 das Thread Object aus DLL No2. "kennen" ?
so wie der Formdesigen bei XbpSLE ja ein AADD(editcontrol, oXbp) ausführt um die SLE in ein
Array aufzunehmen, so in der Art nehme ich auch alle "anderen Objecte" in solche Arrays auf.
ich weiss nicht mehr warum ... (Nebeneffekte ... ?), aber ich habe das zu Cl*pper Zeiten "raus geschmissen" und es durch den "kompletten Path" ersetzt."Set Default To"
... angenommen die Application läuft im Netzwerk. Die Daten sind auf dem Server und die Application wird local gestartet.
So nun ist der Server aber gar nicht physikalisch "vor Ort" sondern eine Remote "Freigabe" eines anderen PC.
mit einem "vollen" Path bekomme ich den Zugriff auf die DBF / Index Dateien, aber IMHO ein
wird nicht auf den Remote PC "wirken", oder ?"Set Default To"
gruss by OHR
Jimmy
Jimmy
- Jan
- Marvin
- Beiträge: 14658
- Registriert: Fr, 23. Sep 2005 18:23
- Wohnort: 49328 Melle
- Hat sich bedankt: 21 Mal
- Danksagung erhalten: 88 Mal
- Kontaktdaten:
Re: Thread und dbf [Erledigt]
Es gibt sicher einen eleganteren Weg. Aber so habe ich das jetzt gemacht:
Der Datenpfad wurde ohnehin in einer Public gespeichert, da ich den an den verschiedensten Stellen immer wieder benötige.
Ich habe eine weitere boolsche Public eingebaut, die speichert, ob in einem anderen Thraed der Pfad geändert wurde. Beim Aufruf einer Tabpage (und damit des entsprechenden Threads) wird nun kontrolliert, ob diese Public auf .T. steht. Wenn ja, wird Set Default To mit der aktuellen Datenpfad-Public belegt, alle Datenbanken werden geschlossen und mit der neuen Pfadangabe wieder geöffnet.
Funktioniert einwandfrei.
Jan
Der Datenpfad wurde ohnehin in einer Public gespeichert, da ich den an den verschiedensten Stellen immer wieder benötige.
Ich habe eine weitere boolsche Public eingebaut, die speichert, ob in einem anderen Thraed der Pfad geändert wurde. Beim Aufruf einer Tabpage (und damit des entsprechenden Threads) wird nun kontrolliert, ob diese Public auf .T. steht. Wenn ja, wird Set Default To mit der aktuellen Datenpfad-Public belegt, alle Datenbanken werden geschlossen und mit der neuen Pfadangabe wieder geöffnet.
Funktioniert einwandfrei.
Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.