Beispiele
Drei vollständige Programme, genau so, wie sie laufen. Sie sind aus den Beispielen im Paket von FoxCore.Runtime 3.4.2 adaptiert, aus dem Ordner ejemplos\: kopieren, in eine .prg einfügen und aus der Visual-FoxPro-IDE ausführen.
.prg im Paket lesen den JWT aus einer Datei auf der Platte, weil sie einzelne Dateien sind, die man von Hand startet und ihn irgendwoher nehmen muss; hier steht er in einer Konstanten, so wie es eine echte Anwendung macht. Siehe Lizenzierung.1. Eine lange Aufgabe, die sagt, wo sie steht
Der Worker ruft runtime.Progress() auf, und hier wird es auf beide Arten abgeholt: durch Fragen mit GetProgress() und durch Benachrichtigung über einen Sink. Die zweite ist die, die man verstanden haben sollte.
LOCAL loRt, loEco, lcId, lcScript, lcJwt
lcJwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...." && hier den JWT aus Ihrem Kundenportal einfügen
loRt = CREATEOBJECT("FoxCore.Runtime")
IF !loRt.Activate(lcJwt)
MESSAGEBOX("La licencia de FoxCore no es valida.", 16, "FoxCore")
RETURN
ENDIF
loRt.Attach(_VFP)
loEco = CREATEOBJECT("EcoDeProgreso")
? "sink aceptado :", loRt.SetEventSink(loEco)
TEXT TO lcScript NOSHOW
FOR i = 1 TO 5
runtime.Progress(i * 20, 'paso ' + TRANSFORM(i) + ' de 5')
=INKEY(0.2)
ENDFOR
runtime.Log('info', 'terminado sin novedad')
RETURN 'listo'
ENDTEXT
lcId = loRt.RunScript(lcScript, "con progreso")
DO WHILE !loRt.IsCompleted(lcId)
loRt.Pump() && der Sink wird VON HIER aufgerufen
ENDDO
loRt.Pump(200, 1000) && eine letzte Runde: es können Meldungen in der Warteschlange sein
? "avisos recibidos :", loEco.nAvisos
? "ultimo aviso :", loEco.cUltimo
? "ultimo log :", loEco.cLog
? "y sin sink :", loRt.GetProgress(lcId), loRt.GetProgressMessage(lcId)
loRt.ClearEventSink() && wichtig: solange sie ihn hält, lebt Ihr Objekt
loRt.Shutdown()
RETURN
DEFINE CLASS EcoDeProgreso AS Custom
nAvisos = 0
cUltimo = ""
cLog = ""
*-- OnProgress y OnLog son OBLIGATORIOS: sin los dos, SetEventSink da .F.
PROCEDURE OnProgress(tcTaskId, tnPercent, tcMessage)
THIS.nAvisos = THIS.nAvisos + 1
THIS.cUltimo = TRANSFORM(tnPercent) + "% " + TRANSFORM(tcMessage)
ENDPROC
PROCEDURE OnLog(tcTaskId, tcLevel, tcMessage)
THIS.cLog = TRANSFORM(tcLevel) + ": " + TRANSFORM(tcMessage)
ENDPROC
*-- Este es opcional: se detecta si esta, y si no, no pasa nada.
PROCEDURE OnTaskCompleted(tcTaskId, tcState)
ENDPROC
ENDDEFINEWas Sie sehen werden
sink aceptado : .T.
avisos recibidos : 5
ultimo aviso : 100% paso 5 de 5
ultimo log : info: terminado sin novedad
y sin sink : 100,00 paso 5 de 52. Eine Tabelle auf mehrere Worker verteilen
Das meistgefragte Rezept, und das am häufigsten falsch gemachte. Entscheidend ist: nicht der Cursor wird verteilt, sondern der BEREICH. Jeder Worker öffnet die Tabelle selbst und bearbeitet einen Abschnitt, also ist nichts geteilt und es braucht keine Sperren.
LOCAL loRt, lcDbf, i, lnDesde, lnHasta, lnPorTramo, lnTotal, lnHechas, lcTerm, lcJwt
LOCAL ARRAY laIds[4], laTerm[1]
lcJwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...." && hier den JWT aus Ihrem Kundenportal einfügen
*-- Una tabla de ejemplo con 400 lineas
CREATE CURSOR ventas (id I, importe Y)
FOR i = 1 TO 400
INSERT INTO ventas VALUES (i, i * 1.25)
ENDFOR
lcDbf = ADDBS(SYS(2023)) + "r09_ventas.dbf"
COPY TO (lcDbf)
USE IN SELECT("ventas")
loRt = CREATEOBJECT("FoxCore.Runtime")
IF !loRt.Activate(lcJwt)
MESSAGEBOX("La licencia de FoxCore no es valida.", 16, "FoxCore")
RETURN
ENDIF
loRt.Attach(_VFP)
loRt.MaxWorkers = 4
*-- Cuatro tramos de 100. jeder Worker öffnet die Tabelle SELBST y suma el suyo.
lnPorTramo = 100
FOR i = 1 TO 4
lnDesde = (i - 1) * lnPorTramo + 1
lnHasta = i * lnPorTramo
laIds[i] = loRt.RunScript( ;
"USE '" + lcDbf + "' IN 0 SHARED ALIAS ventas" + CHR(13) + CHR(10) + ;
"SELECT ventas" + CHR(13) + CHR(10) + ;
"SUM importe TO lnT FOR BETWEEN(id, " + TRANSFORM(lnDesde) + ", " + TRANSFORM(lnHasta) + ")" + CHR(13) + CHR(10) + ;
"USE IN ventas" + CHR(13) + CHR(10) + ;
"RETURN lnT", "tramo " + TRANSFORM(i))
ENDFOR
lnHechas = 0
DO WHILE lnHechas < 4
loRt.Pump()
lcTerm = loRt.PollCompleted()
IF !EMPTY(lcTerm)
lnHechas = lnHechas + ALINES(laTerm, lcTerm, 1, ";")
ENDIF
ENDDO
*-- und zusammengefuhrt wird hier, wo es einen einzigen Thread gibt
lnTotal = 0
FOR i = 1 TO 4
? " tramo " + TRANSFORM(i) + " :", loRt.GetState(laIds[i]), loRt.GetResult(laIds[i])
IF loRt.GetState(laIds[i]) == "Completed"
lnTotal = lnTotal + loRt.GetResult(laIds[i])
ENDIF
ENDFOR
? "total en paralelo :", lnTotal, " (esperado 100250,00)"
ERASE (lcDbf)
loRt.Shutdown()
RETURNWas Sie sehen werden
tramo 1 : Completed 6312,50
tramo 2 : Completed 18812,50
tramo 3 : Completed 31312,50
tramo 4 : Completed 43812,50
total en paralelo : 100250,00 (esperado 100250,00)3. Ein eigener Handler, vom Worker aufgerufen
Der klassische Fall: eine laufende Nummer. Acht Prozesse fragen gleichzeitig nach einer Nummer und keine einzige ist doppelt, mit einem Objekt, das keinen einzigen Lock hat.
LOCAL loRt, loCaja, i, lnHechas, lcTerminadas, lcJwt
LOCAL ARRAY laIds[8], laTerm[1]
lcJwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...." && hier den JWT aus Ihrem Kundenportal einfügen
loRt = CREATEOBJECT("FoxCore.Runtime")
IF !loRt.Activate(lcJwt)
MESSAGEBOX("La licencia de FoxCore no es valida.", 16, "FoxCore")
RETURN
ENDIF
loRt.Attach(_VFP)
loRt.MaxWorkers = 4
loCaja = CREATEOBJECT("CajaDeFolios")
? "handler aceptado :", loRt.RegisterHandler("SiguienteFolio", loCaja, "Siguiente")
FOR i = 1 TO 8
laIds[i] = loRt.RunScript("RETURN runtime.Call('SiguienteFolio', 'FRA')", "folio " + TRANSFORM(i))
ENDFOR
lnHechas = 0
DO WHILE lnHechas < 8
loRt.Pump() && hier werden die Aufrufe bedient
lcTerminadas = loRt.PollCompleted()
IF !EMPTY(lcTerminadas)
lnHechas = lnHechas + ALINES(laTerm, lcTerminadas, 1, ";")
ENDIF
ENDDO
? "folios emitidos :", loCaja.nUltimo
FOR i = 1 TO 8
?? " " + TRANSFORM(loRt.GetResult(laIds[i]))
ENDFOR
loRt.Shutdown()
RETURN
DEFINE CLASS CajaDeFolios AS Custom
nUltimo = 0
*-- ohne einen einzigen Lock, und es braucht keinen: esto se ejecuta en el hilo del host,
*-- de una llamada en una llamada.
FUNCTION Siguiente(tcSerie)
THIS.nUltimo = THIS.nUltimo + 1
RETURN TRANSFORM(tcSerie) + "-" + PADL(THIS.nUltimo, 4, "0")
ENDFUNC
ENDDEFINEWas Sie sehen werden
handler aceptado : .T.
folios emitidos : 8 FRA-0001 FRA-0002 FRA-0003 FRA-0004 FRA-0005 FRA-0006 FRA-0007 FRA-0008FoxCoreClass noch Run() oder WaitFor(). Die Entsprechungstabelle steht in "Was es nicht mehr gibt", am Ende der API-Referenz. Weiter: API-Referenz ->