Examples
Three complete, ready-to-use examples demonstrating the most common FoxCore patterns in real applications.
Example 1: Background CSV file import
Context: Import 1000 rows from a CSV while the UI stays responsive. The progress bar updates every 10 rows via a Timer.
Task procedure (in compiled MyTasks.prg)
* MyTasks.prg
PROCEDURE Task_ImportCSV(loParams, loTask)
LOCAL lcFile, lnHandle, lcLine, lnRow, lnTotal
lcFile = loParams.filePath
lnTotal = loParams.totalRows && caller pre-counts rows
lnHandle = FOPEN(lcFile)
IF lnHandle < 0
loTask.Error = "Cannot open file: " + lcFile
RETURN
ENDIF
lnRow = 0
* Skip header line
lcLine = FGETS(lnHandle)
DO WHILE !FEOF(lnHandle)
lcLine = FGETS(lnHandle)
IF EMPTY(lcLine)
LOOP
ENDIF
* Parse CSV columns (simplified)
LOCAL laFields[1]
lnRow = lnRow + 1
* -- insert record into target table --
* INSERT INTO imports (col1, col2) VALUES (...)
* Update progress every 10 rows
IF MOD(lnRow, 10) == 0
loTask.Progress = INT((lnRow / lnTotal) * 100)
ENDIF
ENDDO
FCLOSE(lnHandle)
loTask.Progress = 100
loTask.Result = TRANSFORM(lnRow) + " rows imported successfully."
ENDPROC Main form -- start the import
* frmImport.Init or button Click handler
LOCAL loParams
THIS.oCore = CREATEOBJECT("FoxCore.FoxCoreClass")
loParams = CREATEOBJECT("Empty")
ADDPROPERTY(loParams, "filePath", "C:dataimport.csv")
ADDPROPERTY(loParams, "totalRows", 1000)
THIS.oTask = THIS.oCore.Run("Task_ImportCSV", loParams)
* Enable timer to poll progress
THIS.Timer1.Enabled = .T.
THIS.cmdImport.Enabled = .F. && disable button while running Form Timer (interval: 500 ms)
PROCEDURE Timer1_Timer
IF ISNULL(THIS.oTask) OR EMPTY(THIS.oTask.Status)
RETURN
ENDIF
THIS.oProgressBar.Value = THIS.oTask.Progress
THIS.lblStatus.Caption = THIS.oTask.Status + " -- " + ;
TRANSFORM(THIS.oTask.Progress) + "%"
DO CASE
CASE THIS.oTask.Status == "Done"
THIS.Timer1.Enabled = .F.
THIS.cmdImport.Enabled = .T.
MESSAGEBOX(THIS.oTask.Result, 64, "Import complete")
CASE THIS.oTask.Status == "Failed"
THIS.Timer1.Enabled = .F.
THIS.cmdImport.Enabled = .T.
MESSAGEBOX("Error: " + THIS.oTask.Error, 48, "Import failed")
ENDCASE
ENDPROC Example 2: Background report generation
Context: Generate a PDF/Excel report without freezing VFP. The OnComplete handler automatically opens the file when done.
Task procedure -- generate the report
* MyTasks.prg (continued)
PROCEDURE Task_GenerateReport(loParams, loTask)
LOCAL lcOutputPath, lcReportFrx
lcReportFrx = loParams.reportPath && .frx file path
lcOutputPath = loParams.outputPath && destination PDF path
loTask.Progress = 10
* Build the report datasource
* (open cursors, set relations, etc.)
loTask.Progress = 30
* Run the VFP report to file
* REPORT FORM (lcReportFrx) TO FILE (lcOutputPath) NOCONSOLE PDF
loTask.Progress = 80
* Verify output exists
IF !FILE(lcOutputPath)
loTask.Error = "Report file was not created: " + lcOutputPath
RETURN
ENDIF
loTask.Progress = 100
loTask.Result = lcOutputPath && pass path back to caller
ENDPROC Form code -- launch and set up callback
* Button: Generate Report
LOCAL loCore, loParams, loTask
loCore = CREATEOBJECT("FoxCore.FoxCoreClass")
loParams = CREATEOBJECT("Empty")
ADDPROPERTY(loParams, "reportPath", "C:
eportssales.frx")
ADDPROPERTY(loParams, "outputPath", "C:
eportssales_" + ;
TRANSFORM(DATE(), "@YMD") + ".pdf")
loTask = loCore.Run("Task_GenerateReport", loParams)
* Set callback -- FoxCore calls this when done
loTask.OnComplete = "OnReportReady"
loTask.OnFailed = "OnReportFailed"
* ... UI continues normally ...
PROCEDURE OnReportReady(loTask)
* Open the generated file with the default PDF viewer
ShellExecute(0, "open", loTask.Result, "", "", 1)
MESSAGEBOX("Report ready: " + loTask.Result, 64, "Done")
ENDPROC
PROCEDURE OnReportFailed(loTask)
MESSAGEBOX("Report generation failed:" + CHR(13) + ;
loTask.Error, 48, "Error")
ENDPROC Example 3: Parallel sync of 3 remote APIs
Context: Synchronize data from 3 different REST APIs simultaneously. Use RunAll to launch them in parallel and collect results.
Task procedures -- one per API
* MyTasks.prg (continued)
PROCEDURE Task_SyncSalesAPI(loParams, loTask)
LOCAL loHttp
loHttp = CREATEOBJECT("WinFx.HttpRequest")
loHttp.Open("GET", loParams.endpoint)
loHttp.WithBearer(loParams.apiKey)
loHttp.Send("")
loTask.Progress = 50
IF loHttp.StatusCode == 200
loTask.Result = loHttp.ResponseText
ELSE
loTask.Error = "HTTP " + TRANSFORM(loHttp.StatusCode) + ;
": " + loHttp.StatusText
ENDIF
loHttp = .NULL.
ENDPROC
PROCEDURE Task_SyncInventoryAPI(loParams, loTask)
* Same pattern as Task_SyncSalesAPI but different endpoint
LOCAL loHttp
loHttp = CREATEOBJECT("WinFx.HttpRequest")
loHttp.Open("GET", loParams.endpoint)
loHttp.WithBearer(loParams.apiKey)
loHttp.Send("")
loTask.Progress = 50
IF loHttp.StatusCode == 200
loTask.Result = loHttp.ResponseText
ELSE
loTask.Error = "HTTP " + TRANSFORM(loHttp.StatusCode)
ENDIF
loHttp = .NULL.
ENDPROC
PROCEDURE Task_SyncCRMAPI(loParams, loTask)
* Same pattern as above for CRM endpoint
LOCAL loHttp
loHttp = CREATEOBJECT("WinFx.HttpRequest")
loHttp.Open("GET", loParams.endpoint)
loHttp.WithBearer(loParams.apiKey)
loHttp.Send("")
loTask.Progress = 50
IF loHttp.StatusCode == 200
loTask.Result = loHttp.ResponseText
ELSE
loTask.Error = "HTTP " + TRANSFORM(loHttp.StatusCode)
ENDIF
loHttp = .NULL.
ENDPROC Main code -- RunAll and collect results
LOCAL loCore, laNames[3], loResults
LOCAL loP1, loP2, loP3
loCore = CREATEOBJECT("FoxCore.FoxCoreClass")
loCore.MaxWorkers = 3 && allow all 3 to run truly in parallel
* Build parameter objects
loP1 = CREATEOBJECT("Empty")
ADDPROPERTY(loP1, "endpoint", "https://sales-api.example.com/sync")
ADDPROPERTY(loP1, "apiKey", "sk_sales_abc123")
loP2 = CREATEOBJECT("Empty")
ADDPROPERTY(loP2, "endpoint", "https://inventory-api.example.com/sync")
ADDPROPERTY(loP2, "apiKey", "sk_inv_xyz789")
loP3 = CREATEOBJECT("Empty")
ADDPROPERTY(loP3, "endpoint", "https://crm-api.example.com/sync")
ADDPROPERTY(loP3, "apiKey", "sk_crm_def456")
* RunAll accepts procedure names only; params are supplied per-task
* via individual Run() calls collected into an array
LOCAL loT1, loT2, loT3
loT1 = loCore.Run("Task_SyncSalesAPI", loP1)
loT2 = loCore.Run("Task_SyncInventoryAPI", loP2)
loT3 = loCore.Run("Task_SyncCRMAPI", loP3)
* Wait for all three (30 second total timeout)
loCore.WaitFor(loT1, 30000)
loCore.WaitFor(loT2, 30000)
loCore.WaitFor(loT3, 30000)
* Collect and report results
LOCAL lcSummary
lcSummary = ""
IF loT1.Status == "Done"
* Process loT1.Result (JSON from sales API)
lcSummary = lcSummary + "Sales: OK" + CHR(13)
ELSE
lcSummary = lcSummary + "Sales: FAILED (" + loT1.Error + ")" + CHR(13)
ENDIF
IF loT2.Status == "Done"
lcSummary = lcSummary + "Inventory: OK" + CHR(13)
ELSE
lcSummary = lcSummary + "Inventory: FAILED (" + loT2.Error + ")" + CHR(13)
ENDIF
IF loT3.Status == "Done"
lcSummary = lcSummary + "CRM: OK"
ELSE
lcSummary = lcSummary + "CRM: FAILED (" + loT3.Error + ")"
ENDIF
MESSAGEBOX(lcSummary, 64, "Sync complete") Example 4: Multiple tasks in parallel (RunMultiple)
Runs an array of scripts simultaneously and waits for all to finish with WaitAll.
DO "ruta\FoxCore-VFP9-v1.0.app"
LOCAL ARRAY laScripts[3]
TEXT TO laScripts[1] NOSHOW
LOCAL lnSum, i
lnSum = 0
FOR i = 1 TO 1000000
lnSum = lnSum + i
ENDFOR
RETURN "Suma: " + TRANSFORM(lnSum)
ENDTEXT
TEXT TO laScripts[2] NOSHOW
WAIT WINDOW "Procesando archivo..." TIMEOUT 3
RETURN "Archivo procesado"
ENDTEXT
TEXT TO laScripts[3] NOSHOW
WAIT WINDOW "Conectando red..." TIMEOUT 2
RETURN "Conexion OK"
ENDTEXT
PUBLIC loHandler, loTasks
loHandler = CREATEOBJECT("TaskHandler")
loTasks = _screen.FoxCore.RunMultiple(@laScripts)
_screen.FoxCore.AddEventListener("OnTaskComplete", loHandler, "OnComplete")
_screen.FoxCore.AddEventListener("OnTaskFailed", loHandler, "OnFailed")
IF !_screen.FoxCore.WaitAll(loTasks, 60)
MESSAGEBOX("Timeout - no todas completadas", 48)
ELSE
FOR EACH loTask IN loTasks
? loTask.GetStatus(), loTask.GetResult()
ENDFOR
ENDIF
DEFINE CLASS TaskHandler AS CUSTOM
PROCEDURE OnComplete(toTask, tvResult)
? "OK:", TRANSFORM(tvResult)
ENDPROC
PROCEDURE OnFailed(toTask, tcError)
? "ERROR:", tcError
ENDPROC
ENDDEFINE Example 5: WaitAny — process whichever finishes first
Useful when searching multiple sources and you only need the first valid result.
DO "ruta\FoxCore-VFP9-v1.0.app"
LOCAL ARRAY laScripts[3]
TEXT TO laScripts[1] NOSHOW
WAIT WINDOW "Fuente 1 (lenta)..." TIMEOUT 4
RETURN .NULL. && sin resultado
ENDTEXT
TEXT TO laScripts[2] NOSHOW
WAIT WINDOW "Fuente 2 (rapida)..." TIMEOUT 2
RETURN "Resultado encontrado en fuente 2"
ENDTEXT
TEXT TO laScripts[3] NOSHOW
WAIT WINDOW "Fuente 3 (media)..." TIMEOUT 3
RETURN "Resultado encontrado en fuente 3"
ENDTEXT
PUBLIC loTasks
loTasks = _screen.FoxCore.RunMultiple(@laScripts)
LOCAL lnIdx, lvResult
lvResult = .NULL.
DO WHILE ISNULL(lvResult)
lnIdx = _screen.FoxCore.WaitAny(@loTasks, 10)
IF lnIdx > 0
lvResult = loTasks[lnIdx].GetResult()
IF !ISNULL(lvResult)
? "Primera respuesta valida (fuente " + TRANSFORM(lnIdx) + "):", TRANSFORM(lvResult)
* Cancelar las restantes
LOCAL i
FOR i = 1 TO ALEN(loTasks)
IF i <> lnIdx AND loTasks[i].GetStatus() = "Running"
loTasks[i].Cancel("Ya tenemos resultado")
ENDIF
ENDFOR
ENDIF
ELSE
? "Timeout - ninguna fuente respondio"
EXIT
ENDIF
ENDDO Example 6: Passing variables to a task (SetVariable)
Variables passed with SetVariable are available directly in the task execution context.
DO "ruta\FoxCore-VFP9-v1.0.app"
LOCAL lcRuta, lnFiles, lcPrefix
lcRuta = "C:\datos\"
lnFiles = 5
lcPrefix = "reporte_"
TEXT TO lcScript NOSHOW
* lcRuta, lnFiles, lcPrefix estan disponibles aqui
LOCAL i, lcFile
FOR i = 1 TO lnFiles
lcFile = lcRuta + lcPrefix + TRANSFORM(i) + ".txt"
STRTOFILE("Contenido " + TRANSFORM(i), lcFile)
Task.Progress("Creando archivo " + TRANSFORM(i), i/lnFiles*100)
ENDFOR
RETURN "Se crearon " + TRANSFORM(lnFiles) + " archivos en " + lcRuta
ENDTEXT
LOCAL loTask
loTask = _screen.FoxCore.NewTask(lcScript)
loTask.SetVariable("lcRuta", lcRuta)
loTask.SetVariable("lnFiles", lnFiles)
loTask.SetVariable("lcPrefix", lcPrefix)
loTask.Run()
IF loTask.Wait(30)
? "Resultado:", loTask.GetResult()
ENDIF Example 7: Sequential tasks (RunMultipleSequential)
Runs an array of scripts in order. Each task can read the previous result via gvPreviousTaskResult.
DO "ruta\FoxCore-VFP9-v1.0.app"
LOCAL ARRAY laScripts[3]
TEXT TO laScripts[1] NOSHOW
* Paso 1: obtener datos
RETURN "datos_obtenidos"
ENDTEXT
TEXT TO laScripts[2] NOSHOW
* Paso 2: procesar (gvPreviousTaskResult = "datos_obtenidos")
RETURN "procesado_desde_" + TRANSFORM(gvPreviousTaskResult)
ENDTEXT
TEXT TO laScripts[3] NOSHOW
* Paso 3: exportar
RETURN "exportado: " + TRANSFORM(gvPreviousTaskResult)
ENDTEXT
PUBLIC loResults
loResults = _screen.FoxCore.RunMultipleSequential(@laScripts, .F.) && .F. = detener ante error
_screen.FoxCore.WaitAll(loResults, 120)
FOR EACH loTask IN loResults
? loTask.GetStatus(), loTask.GetResult()
ENDFOR Example 8: Real-time monitoring with statistics
Monitoring loop that shows the status of all tasks while they run in parallel.
DO "ruta\FoxCore-VFP9-v1.0.app"
* (preparar laScripts y loTasks como en el Ejemplo 4)
LOCAL loStats, loSummary, lnStart
lnStart = SECONDS()
DO WHILE !_screen.FoxCore.WaitAll(loTasks, 0.5)
CLEAR
loStats = _screen.FoxCore.GetSystemStats()
loSummary = _screen.FoxCore.GetTasksSummary()
? "Tiempo transcurrido: " + TRANSFORM(INT(SECONDS()-lnStart)) + "s"
? "Procesadores logicos: " + TRANSFORM(loStats.LogicalProcessors)
? "Tareas activas: " + TRANSFORM(loStats.ActiveTasks) + "/" + TRANSFORM(loStats.MaxTasks)
? "Progreso general: " + TRANSFORM(_screen.FoxCore.GetProgress()) + "%"
? "Completadas/Fallidas: " + TRANSFORM(loSummary.completed) + "/" + TRANSFORM(loSummary.failed)
ENDDO
loSummary = _screen.FoxCore.GetTasksSummary()
? "=== FINAL ==="
? "Total:", loSummary.total, " OK:", loSummary.completed, " Error:", loSummary.failed Back to reference: API Reference →