API-Referenz
Vollstandige Referenz von FoxCore.Runtime 3.4.2: die sechs COM-Typen, ihre Mitglieder und was jedes liefert, wenn etwas schiefgeht.
Die Engine starten
Das Minimum, das funktioniert: erzeugen, Lizenz aktivieren, an den Thread binden, eine Aufgabe starten, während sie läuft pumpen und beenden.
LOCAL loRt, lcId
loRt = CREATEOBJECT("FoxCore.Runtime")
? loRt.Activate(lcJwt) && .T. -- Ihre Lizenz, als Zeichenkette
loRt.Attach(_VFP) && bindet die Runtime AN DIESEN Thread
loRt.MaxWorkers = 8
lcId = loRt.RunScript("RETURN 6 * 42", "la primera") && das Skript läuft in einem ANDEREN VFP-Prozess
DO WHILE !loRt.IsCompleted(lcId)
loRt.Pump() && Pump() bedient die Worker; ohne es warten sie nur
DOEVENTS
ENDDO
? loRt.GetState(lcId) && Completed
? loRt.GetResult(lcId) && 252
? loRt.GetError(lcId) && ""
loRt.Shutdown() && IMMER: es beendet die WorkerDer JWT wird per Code ubergeben: es gibt keine Datei zu kopieren. Woher Sie ihn bekommen und was ohne ihn passiert, steht auf der Seite Lizenzierung.
Die sechs Typen
Drei Klassen und ihre drei Schnittstellen. Einen siebten Typ gibt es nicht, und es wird ihn nicht geben: zweimal sah es so aus, als brauchte es einen - das Ergebnis von TryCall, dann GetStats - und beide Male war die Antwort eine JSON-Zeichenkette.
| Klasse | Schnittstelle | ProgId | Was es ist |
|---|---|---|---|
FoxRuntime | IFoxRuntime | FoxCore.Runtime | Das Objekt, das der Host erzeugt. Es ist die Engine: Lizenz, Optionen, Aufgaben, Pumpen, Ereignisse und Handler. |
FoxTaskHandle | IFoxTask | — | Das Handle, das NewTask() liefert. Zucker: es hält keinen Zustand, jede Eigenschaft fragt die Registry. |
WorkerBridge | IFoxWorker | — | Die Variable runtime INNERHALB des Skripts. Mehr sieht der Worker vom Hauptprozess nicht. |
FoxCore.Runtime
Lebenszyklus
| Mitglied | Liefert | Hinweise |
|---|---|---|
Activate(cLicenseKey) | L | Prueft den JWT. Wirft bei ungultiger Lizenz NIE: liefert .F., und blockiert werden die Aufgaben, nicht der Lebenszyklus. |
Attach(oHost, nVersion, cRuntimeMode) | — | Bindet die Runtime AN DEN THREAD, aus dem sie aufgerufen wird. Normalerweise loRt.Attach(_VFP). Die letzten beiden sind optional. |
Shutdown() | — | Idempotent. ES BEENDET DIE WORKER. Immer aufrufen. |
Ping() | C | "FoxCore.Runtime 3.4.2". Funktioniert in jedem Zustand, auch nach Shutdown(). |
Version | C | Nur lesbar. |
State | C | Created | Activated | Attached | ShuttingDown | ShutDown. Eine ZEICHENKETTE, kein Enum: kein Zahlenwert quert COM. |
IsRunning | L | .T. zwischen Attach() und Shutdown(). |
IsLicensed | L | .T., wenn der JWT gültig ist. Seit 3.4.0 gibt es KEINE Ausnahme nach Modus: auch außerhalb der IDE erforderlich. |
Optionen
Alle lesbar und schreibbar. Nach dem Erzeugen des Objekts und vor dem Start von Aufgaben setzen.
| Eigenschaft | Standard | Was sie steuert |
|---|---|---|
MaxWorkers | min(nucleos, 8) | Gleichzeitige Worker-Prozesse. Bereich 1-64. Faustregel: physische Kerne. |
DefaultTimeoutSeconds | 30 | Frist pro Aufgabe. Bereich 1-86.400. Nach Ablauf endet die Aufgabe als TimedOut und der Worker stirbt. |
WorkerProgId | "VisualFoxpro.Application.9" | Welcher Prozess als Worker dient: VFP 9, VFP Advanced oder Ihre eigene registrierte EXE. Geprueft wird das FORMAT, nicht die Existenz: ob er taugt, sagt ProbeWorker(). |
KeepCompletedTasks | 200 | Wie viele BEENDETE Aufgaben die Registry behalt, bevor die altesten verworfen werden. Wichtig bei grossen Stapeln. |
MaxTasksPerWorker | 1 | Wie viele Aufgaben ein Worker bedient, bevor er recycelt wird. 1 = ein Prozess pro Aufgabe, volle Isolation. 0 = ohne Limit. |
WorkerInitScript | "" | Skript, das EINMAL PRO WORKER vor seiner ersten Aufgabe läuft. Hier kommt die Umgebung hin. |
WorkerResetScript | "" | Skript, das ZWISCHEN AUFGABEN eines wiederverwendeten Workers läuft. Hier wird aufgeraumt. |
WorkerInitFailurePolicy | "abort" | Was bei einem Fehler im Startskript passiert: "abort" bricht ab, "tolerate" lasst dessen eigenes ON ERROR ubernehmen und weitermachen. |
PumpMaxItems | 8 | Wie viel jedes Pump() abarbeitet. |
PumpMaxMilliseconds | 20 | Zeitbudget jedes Pump(). |
RequestTimeoutSeconds | 15 | Wie lange ein in Call() blockierter Worker auf ein Timeout wartet. Das verhindert, dass ein Host, der nicht pumpt, einen Worker haengen lässt. |
SecurityMode | "Safe" | "Safe" ist der einzige echte Modus. |
AuditLevel | "basic" | off | basic | full. |
Aufgaben
| Mitglied | Liefert | Hinweise |
|---|---|---|
RunScript(cScript, cTaskName) | C | Erzeugt, reiht ein und liefert die Task-ID. DER NORMALE WEG. |
NewTask(cScript, cTaskName) | FoxTaskHandle | Erzeugt OHNE Einreihen, um sie vorher zu konfigurieren (etwa mit SetTaskTimeout). |
Start(cTaskId) | L | Reiht eine erzeugte Aufgabe ein. .F., wenn sie nicht existiert oder schon gestartet wurde. |
GetState(cTaskId) | C | Created | Queued | Running | Completed | Failed | Cancelled | TimedOut, und NotFound für eine unbekannte oder bereits verworfene ID. |
GetResult(cTaskId) | valor | Das RETURN des Skripts. .NULL., solange es nicht erfolgreich beendet ist; leere Zeichenkette bei unbekannter ID. |
GetError(cTaskId) | C | Leere Zeichenkette, wenn kein Fehler; "Task not found." bei unbekannter ID. |
IsCompleted(cTaskId) | L | .T. in jedem Endzustand UND AUCH bei einer nicht existierenden ID - mit Absicht: sonst wurde die kanonische Schleife ewig drehen, sobald die Bereinigung die Aufgabe entfernt. |
GetProgress(cTaskId) | N | 0-100. Funktioniert auch, wenn niemand pumpt. |
GetProgressMessage(cTaskId) | C | Die letzte Meldung, sonst leere Zeichenkette. |
PollCompleted() | C | Die seit dem LETZTEN AUFRUF beendeten IDs, durch ";" getrennt. Ein COM-Aufruf pro Runde statt N. LESEN LEERT ES. |
SetTaskTimeout(cTaskId, nSegundos) | L | Frist für EINE Aufgabe. Nur vor dem Start: NewTask + dies + Start. .F., wenn sie schon läuft oder nicht existiert. |
Forget(cTaskId) | L | Vergisst eine BEENDETE Aufgabe und gibt ihr Ergebnis frei. .F., wenn sie nicht existiert oder noch läuft. |
Abbruch
| Mitglied | Liefert | Hinweise |
|---|---|---|
Cancel(cTaskId) | L | KOOPERATIV: setzt das Flag, das das Skript mit runtime.IsCancelled() liest, und entsperrt sofort jeden laufenden Call. .F., wenn es nichts zu stoppen gibt. |
CancelAll() | N | Wie viele abgebrochen wurden. |
Kill(cTaskId) | L | HART: beendet den Prozess per PID. Fur ein Skript, das das Flag nie prueft, der einzige Weg. Endet als Cancelled mit "Killed by host." |
Pumpen
| Mitglied | Liefert | Hinweise |
|---|---|---|
Pump(nMaxItems, nMaxMs) | N | Bedient zuerst die synchronen Anfragen - hinter jeder steht ein BLOCKIERTER Worker - und danach die Benachrichtigungen. Beide Parameter 0 oder nicht angegeben = die Optionen verwenden. |
Ereignisse
| Mitglied | Liefert | Hinweise |
|---|---|---|
SetEventSink(oSink) | L | Die Runtime meldet AUS Pump() HERAUS, in Ihrem Thread. Liefert .F. OHNE ZU WERFEN, wenn dem Objekt die Pflichtmethoden fehlen. |
ClearEventSink() | — | Im Destroy des Formulars freigeben: solange die Runtime es hält, bleibt das Formular am Leben. |
Der Sink muss OnProgress(tcTaskId, tnPercent, tcMessage) und OnLog(tcTaskId, tcLevel, tcMessage) haben, beide Pflicht, und kann OnTaskCompleted(tcTaskId, tcState) und OnTaskFailed(tcTaskId, tcError) haben, die erkannt werden, wenn sie da sind. Der Sink ist zusätzlich: GetProgress() und GetProgressMessage() funktionieren auch ohne ihn.
Handler - was ein Worker vom Host anfordern kann
| Mitglied | Liefert | Hinweise |
|---|---|---|
RegisterHandler(cName, oTarget, cMethodName) | L | cMethodName ist standardmassig "Invoke". Liefert .F. OHNE ZU WERFEN, wenn der Name leer ist, Leerzeichen enthalt, 64 Zeichen ubersteigt, schon registriert ist, einer der eingebauten ist ODER WENN DAS OBJEKT DIESE METHODE NICHT BIETET - diese letzte Prufung lasst den Fehler im Init des Formulars auftauchen und nicht sechs Stunden spater im Worker. |
UnregisterHandler(cName) | L | .F., wenn er nicht registriert war. |
GetHandlerNames() | C | Die Namen, durch ";" getrennt, alphabetisch. Das ist die VOLLSTANDIGE Flache dessen, was ein Worker anfordern kann. Drei eingebaute sind immer da: echo, upper und add. |
Gemeinsame Tafel
Löst "der Worker braucht die Konfiguration des Hosts" ohne Roundtrip und ohne Pump.
| Mitglied | Liefert | Hinweise |
|---|---|---|
Publish(cName, uValue) | — | Veröffentlicht einen Wert, den die Worker mit runtime.GetValue() OHNE Warteschlangen- und Pump-Kosten lesen. |
GetValue(cName) | valor | .NULL., wenn er nicht existiert. |
Sonstiges
| Mitglied | Liefert | Hinweise |
|---|---|---|
GetStats() | C | Die Momentaufnahme der Engine als flache JSON-ZEICHENKETTE. Sie liefert eine Zeichenkette und kein Objekt, aus zwei Grunden: ein COM-Objekt kostet einen Roundtrip PRO EIGENSCHAFT, und ein neuer Typ wurde den Vertrag der sechs Typen brechen. |
ProbeWorker(cProgId) | C | Taugt diese ProgId als Worker? Die Antwort kommt vom AUSFÜHREN. Ohne Argument wird die aktuelle WorkerProgId geprüft. |
GetAuditPath() | C | WO das Journal LIEGEN WURDE. Es schreibt nichts. |
SetCorrelation(cId, cName, cValue) | L | Ein GESCHLOSSENES Vokabular aus sieben Namen. .F. ohne zu schreiben für alles andere. |
GetCorrelation(cId, cName) | C | Leere Zeichenkette, wenn nicht gesetzt. |
Was GetStats() liefert
Eine flache JSON-Zeichenkette, mit jsonfox in einem einzigen Aufruf geparst. Es gibt zwei Familien von Zahlern, und sie zu verwechseln ist teuer:
- createdEver, finishedEver, completedEver, failedEver, cancelledEver, timedOutEver - sie zahlen, was seit dem Start der Runtime PASSIERT ist, und gehen NIE zurück. Mit ihnen zeichnet man den Fortschritt.
- total, created, completed, failed, cancelled, timedOut - sie sind die MOMENTAUFNAHME der Registry, und sie gehen zurück: Forget() und die Bereinigung ziehen ab. Mit ihnen sieht man, was gerade lebt.
{
"state": "Attached",
"workerProgId": "VisualFoxpro.Application.9",
"maxWorkers": 8,
"queued": 22,
"running": 8,
"peakRunning": 8,
"liveWorkers": 8,
"createdEver": 30,
"finishedEver": 0,
"completedEver": 0,
"failedEver": 0,
"cancelledEver": 0,
"timedOutEver": 0,
"total": 30,
"created": 0,
"completed": 0,
"failed": 0,
"cancelled": 0,
"timedOut": 0,
"purged": 0,
"keepCompletedTasks": 200,
"completedPending": 0,
"completedDropped": 0,
"pendingRequests": 0,
"expiredRequests": 0,
"pendingNotifications": 3,
"droppedTelemetry": 0,
"handlers": 2,
"requestsHandled": 47,
"handlerErrors": 0
}FoxTaskHandle
Von NewTask() geliefert. Es hält keinen Zustand: jede Eigenschaft delegiert an die Registry der Engine. Es ist Zucker - alles, was es tut, geht auch mit der taskId und den Runtime-Methoden.
| Mitglied | Typ | Hinweise |
|---|---|---|
Id | C | Die taskId. DIE KANONISCHE WAHRHEIT ist diese Zeichenkette: sie quert COM ohne Lebensdauer-Kosten und lässt sich in ein Ticket einfügen. |
Name | C | Der bei der Erzeugung vergebene Name. |
State | C | Dasselbe wie GetState(Id). |
Result | valor | Dasselbe wie GetResult(Id). |
Error | C | Dasselbe wie GetError(Id). |
IsCompleted | L | Dasselbe wie IsCompleted(Id). |
OperationId | C | Existiert und ist IMMER eine leere Zeichenkette: Operationen sind nicht implementiert. |
Start() | L | Reiht die Aufgabe ein. Dasselbe wie Start(Id). |
WorkerBridge - die Variable runtime im Skript
Mehr sieht der Worker vom Hauptprozess nicht, und seine Flache ist auf diese Aufgabe begrenzt. Entscheidend ist die Spalte "Blockiert?": nur Call und TryCallJson warten darauf, dass der Host pumpt, denn nur sie fuhren VFP-Code im Hauptprozess aus.
| Mitglied | Blockiert? | Hinweise |
|---|---|---|
TaskId / TaskName | no | Die ID und der Name DIESER Aufgabe. |
ElapsedSeconds | no | Sekunden seit dem Start der Aufgabe. |
Ping() | no | "pong". |
Progress(nPercent, cMessage) | no | Fire-and-forget. Braucht kein Pump und schlägt nicht fehl. Der Prozentwert wird auf 0-100 begrenzt. |
Log(cLevel, cMessage) | no | "info" | "warn" | "error". Fire-and-forget. |
IsCancelled() | no | Eine LOKALE Abfrage, sie berührt den Host nicht. Gedacht für jeden Schleifendurchlauf. |
GetValue(cName) / SetValue(cName, uValue) | no | Gemeinsame Tafel, lokal, ohne Pump. |
Call(cName, arg1..arg8) | SI | Ruft einen Host-Handler auf. Synchron: der Worker wartet, bis der Host pumpt. WIRFT einen OLE-Fehler, wenn der Handler scheitert. |
TryCallJson(cName, arg1..arg8) | SI | Wie Call, aber WIRFT NIE. Liefert JSON: {"ok":true,"value":"42","error":"","errorCode":""}. Der Wert reist IMMER als Zeichenkette. |
Muster
Die zwei Schleifen, die man kennen muss:
- Normaler Stapel: mit RunScript() starten, die IDs behalten und ein DO WHILE drehen, das Pump() und DOEVENTS aufruft, bis IsCompleted() für alle ja sagt.
- Großer Stapel (Hunderte oder Tausende): Aufgabe für Aufgabe zu fragen sind N COM-Aufrufe pro Runde. KeepCompletedTasks erhöhen, PollCompleted() einmal pro Runde aufrufen, das Ergebnis der gelieferten IDs lesen und für jede Forget() aufrufen. Der Fortschritt kommt aus finishedEver, nicht aus completed: mit Forget() in jeder Runde bleibt die Momentaufnahme bei null, und das ist richtig.
Beide, mit vollstandigem Code und den jeweiligen Fallen, stehen auf der Seite Muster.
Was es nicht mehr gibt
Wenn Sie von einer Suchmaschine kommen oder von Code, der für die klassische Engine (WinFx.FoxCore) geschrieben wurde: das hat sich geändert. Die klassische Engine existiert weiter und wird weiter unterstützt; sie ist nicht die, die diese Seite beschreibt.
| Klassische Engine | In FoxCore.Runtime 3.4.2 |
|---|---|
CREATEOBJECT("WinFx.FoxCore") / _screen.FoxCore | CREATEOBJECT("FoxCore.Runtime") - ein anderes COM-Objekt, mit anderer ProgId und anderer GUID. Beide konnen gleichzeitig registriert sein. |
Run(cProc, oParams) | RunScript(cSkript, cName). Es wird nicht mehr der NAME einer Prozedur übergeben, die im Worker existieren muss: übergeben wird das SKRIPT als Text, und der Worker führt es mit EXECSCRIPT() aus. |
RunMultiple(@laTareas) | Kein Aquivalent, mit Absicht: man ruft RunScript() in einer FOR-Schleife auf und behalt die IDs. Eine Methode, die ein Array per Referenz nimmt, quert COM nicht zuverlassig, und sie lieferte ein Container-Objekt: ein Typ mehr, und der Vertrag sind sechs. |
WaitAll() / WaitAny() | Kein Aquivalent, und das ist der eigentliche Unterschied: die Schleife schreibt der HOST, mit Pump() und DOEVENTS. Ein blockierendes WaitFor in VFP ist genau die eingefrorene Oberfläche, die dieses Produkt verhindern soll. |
GetTasksSummary() / GetSystemStats() | GetStats() für die Zahlen (queued, running, liveWorkers) und PollCompleted(), um zu erfahren, wer gerade fertig wurde. Ein Array von Task-Objekten über COM kostet einen Roundtrip pro Eigenschaft und Aufgabe. |
CancelTask(loTask) | Cancel(cTaskId). Identifiziert über die ID, nicht über das Objekt. |
Activate(cClave) | Activate(cJwt), gleicher Name, anderer Schlüssel: seit 3.4.0 gibt es keine Datei, die Lizenz ist ein JWT, das per Code übergeben wird. |
foxcore.lic | Kein Aquivalent: seit 3.4.0 gibt es keine Lizenzdatei. Siehe die Seite Lizenzierung. |
PROCEDURE MiTarea(loParams, loTask) | Im Skript gibt es keine Parameter: es gibt eine Variable namens runtime (WorkerBridge). loTask.Progress = 50 wird zu runtime.Progress(50, "...") und loTask.Result = x wird zu RETURN x. |
Weiter: Lizenzierung ->