Hallo,
ich habe folgendes Problem. Wir migrieren zurzeit von Clipper zu Xbase. Um unseren Kunden auch aus dem alten Clipperprogramm schon neue Funktionen zur Verfügung stellen zur können schreiben wir aus Clipper Anfragen in eine Datenbank. Im Hintergrund läuft auf den Rechnern dann eine Xbase Applikation die diese Anfragen auswertet und die entsprechenden Xbase Programme startet , Rückgaben werden einfach wieder in die Datenbank geschrieben.
Das Programm das im Hintergrund läuft ruft alle paar Sekunden (über einen Zeitgesteuerten Thread) eine Funktion auf die nachguckt ob neue Anfragen da sind. Ist eine neue Anfrage da wird ein neuer Thread gestartet. Indem wird dann die entsprechende Funktion (über DLLs) gestartet. Problem ist jetzt das mein Programm bei jedem dieser Functionsaufrufe mehr Speicher braucht (ca. 4KB pro Aufruf). Lasse ich den 2. Thread weg und rufe die Funktion direkt auf , wird kein zusätzlicher Speicher mehr verbraucht.
Muss ich den zusätzlich gestarteten Thread selbst zerstören oder zerstört dieser sich nach Ablauf selbst? Wenn ja wie kann ich ihn zerstören?
Hoffe ihr könnt mir helfen, danke schonmal
Threads nach ablauf zerstören?
Moderator: Moderatoren
-
- UDF-Programmierer
- Beiträge: 51
- Registriert: Di, 18. Okt 2005 12:35
- Wohnort: 41747 Viersen
- Kontaktdaten:
- AUGE_OHR
- Marvin
- Beiträge: 12906
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 45 Mal
Re: Threads nach ablauf zerstören?
hi,
LOCAL oThread
...
oThread := Thread():new()
oThread:setInterval(10)
oThread:start("EVTHREAD",oDlg,aoChild)
...
//
// set to NIL will terminate Tread
//
oThread:setInterval(NIL)
Zum Thema "mehr Speicher braucht" will ich mich jetzt nicht äussern,
aber "wie misst" du den RAM "Verbrauch" ?
Zur Konstruktion Thread/Dll laden : Da RAM heute nicht mehr das
Problem ist versuche ich immer "alles" zu laden. Auch wird dann
der "wiederholte" Zugriff schneller als von der HD.
Also statt den Thread "immer wieder" aufzurufen sollte man "im Thread"
ein "timeout" einbauen und dann das DBSEEK() machen.
Das Timeout kann man nun "sauber" in die "Thread AppEvent Loop"
einbauen wenn man den 4st. Parameter nimmt.
gruss by OHR
Jimmy
ich fange mal mit der letzten Frage an :ab-software hat geschrieben: Das Programm das im Hintergrund läuft ruft alle paar Sekunden (über einen Zeitgesteuerten Thread) eine Funktion auf die nachguckt ob neue Anfragen da sind. Ist eine neue Anfrage da wird ein neuer Thread gestartet. Indem wird dann die entsprechende Funktion (über DLLs) gestartet. Problem ist jetzt das mein Programm bei jedem dieser Functionsaufrufe mehr Speicher braucht (ca. 4KB pro Aufruf). Lasse ich den 2. Thread weg und rufe die Funktion direkt auf , wird kein zusätzlicher Speicher mehr verbraucht.
Muss ich den zusätzlich gestarteten Thread selbst zerstören oder zerstört dieser sich nach Ablauf selbst?
Wenn ja wie kann ich ihn zerstören?
LOCAL oThread
...
oThread := Thread():new()
oThread:setInterval(10)
oThread:start("EVTHREAD",oDlg,aoChild)
...
//
// set to NIL will terminate Tread
//
oThread:setInterval(NIL)
Zum Thema "mehr Speicher braucht" will ich mich jetzt nicht äussern,
aber "wie misst" du den RAM "Verbrauch" ?
Zur Konstruktion Thread/Dll laden : Da RAM heute nicht mehr das
Problem ist versuche ich immer "alles" zu laden. Auch wird dann
der "wiederholte" Zugriff schneller als von der HD.
Also statt den Thread "immer wieder" aufzurufen sollte man "im Thread"
ein "timeout" einbauen und dann das DBSEEK() machen.
Das Timeout kann man nun "sauber" in die "Thread AppEvent Loop"
einbauen wenn man den 4st. Parameter nimmt.
Code: Alles auswählen
DO WHILE .NOT. lExit
nEvent := xbe_None
DO WHILE nEvent <> xbeP_Close
nEvent := AppEvent( @mp1, @mp2, @oXbp ,6000) // 6000=60Sec
DO CASE
CASE nEvent = xbe_None // timeout
Exit // raus
...
OTHERWISE
oXbp:handleEvent( nEvent, mp1, mp2 )
ENDCASE
ENDDO nEvent <> xbeP_Close
DO WHILE Look4Mail
POP3->(DBSEEK(ID_USER+"0"))
IF FOUND()
...
ELSE
EXIT
ENDIF
ENDDO Look4Mail
ENDDO .NOT. lExit
Jimmy
- andreas
- Der Entwickler von "Deep Thought"
- Beiträge: 1902
- Registriert: Mi, 28. Sep 2005 10:53
- Wohnort: Osnabrück
- Hat sich bedankt: 4 Mal
- Kontaktdaten:
Hallo,
ich hatte das gleiche Problem und habe es genauso gelöst, wie Jimmy vorgeschlagen hat: Funktion ständig im Thread laufen lassen, wo bei zum Warten Sleep() eingesetzt wird. Wenn du die Public-Variable zum Erstellen des Thread benutzt, soltest du diese nach dem Beenden bzw. Starten des Threads auf NIL setzen, wenn du diese nicht mehr brauchst. Dann wird der Thread aus dem Speicher etfernt.
Ich habe bei mir im Fenster zus. ein XBPMLE eingebaut und ein Thread laufen lassen, der die Infos über laufende Threads anzeigt. Jedem Thread habe ich einen Cargo-Wert zugewiesen, damit ich sehen kann, was das überhaupt ist. Du könntest diese zum Testen auch verwenden. Du muss die Ausgabe noch anpassen.
::einAktualisieren - ist ein Checkbox, das die Aktualiesierung abschalten kann, um den Text normal lesen zu können.
Dabei solltest du beachten, dass immer ein Main-Thread vorhanden ist. Dem kannst du einen Namen folgend vergeben:
ich hatte das gleiche Problem und habe es genauso gelöst, wie Jimmy vorgeschlagen hat: Funktion ständig im Thread laufen lassen, wo bei zum Warten Sleep() eingesetzt wird. Wenn du die Public-Variable zum Erstellen des Thread benutzt, soltest du diese nach dem Beenden bzw. Starten des Threads auf NIL setzen, wenn du diese nicht mehr brauchst. Dann wird der Thread aus dem Speicher etfernt.
Ich habe bei mir im Fenster zus. ein XBPMLE eingebaut und ein Thread laufen lassen, der die Infos über laufende Threads anzeigt. Jedem Thread habe ich einen Cargo-Wert zugewiesen, damit ich sehen kann, was das überhaupt ist. Du könntest diese zum Testen auch verwenden. Du muss die Ausgabe noch anpassen.
Code: Alles auswählen
METHOD ThreadInfoAnzeigen()
local aInfo := {}
local cText := ""
if lTerminated
oThreadInfo:setInterval( NIL )
else
bSaveError := ErrorBlock()
ErrorBlock( {|e| Break(e)} )
BEGIN SEQUENCE
aInfo := ThreadInfo( THREADINFO_TID + THREADINFO_FUNCINFO + THREADINFO_TOBJ )
IF ::einAktualisieren:getdata()
cText := "ID / Zeile / Funktion / Name / Interval-Rest / Startcount "
cText += CRLF+"---------------------------------------------------------------"
FOR i := 1 TO len(aInfo)
cText += CRLF+var2char(aInfo[i][1])+" / ";
+var2char(aInfo[i][2])+" / "+var2char(aInfo[i][3]);
+IIF( valtype(aInfo[i][4])=="O", IIF( isMemberVar(aInfo[i][4], "CARGO"), " / "+alltrim(var2char(aInfo[i][4]:cargo)) , " / Fehler: keine Membervariable" ) , " / Fehler: kein Objekt" );
+IIF( valtype(aInfo[i][4])=="O", IIF( isMemberVar(aInfo[i][4], "CARGO"), " / "+alltrim(str(int(val(var2char(aInfo[i][4]:interval))/100))) + "-"+alltrim(str(int(val(var2char(aInfo[i][4]:deltatime))/100))) , " / Fehler: keine Membervariable" ) , " / Fehler: kein Objekt" );
+IIF( valtype(aInfo[i][4])=="O", IIF( isMemberVar(aInfo[i][4], "CARGO"), " / "+alltrim(var2char(aInfo[i][4]:startcount)) , " / Fehler: keine Membervariable" ) , " / Fehler: kein Objekt" )
NEXT
::XBPMLE:setdata( cText )
ENDIF
RECOVER
ErrorBlock( bSaveError )
END SEQUENCE
ErrorBlock( bSaveError )
endif
RETURN self
Dabei solltest du beachten, dass immer ein Main-Thread vorhanden ist. Dem kannst du einen Namen folgend vergeben:
Code: Alles auswählen
ThreadObject():cargo := "Main"
-
- UDF-Programmierer
- Beiträge: 51
- Registriert: Di, 18. Okt 2005 12:35
- Wohnort: 41747 Viersen
- Kontaktdaten: