bcquality/microsoft/knowledge/ui/page-background-tasks.md
Jesper Schulz-Wedde 186d8a1314
Some checks failed
Validate knowledge index / validate-index (push) Has been cancelled
Validate AL review fixtures / validate-review-fixtures (push) Has been cancelled
Validate frontmatter and structure / validate (push) Has been cancelled
Complete AL review knowledge readiness (#108)
* Complete AL review knowledge readiness

Fill telemetry and Query coverage, strengthen thin review domains, correct audited content defects, and add deterministic cheap-model evaluation and reference-integrity safeguards.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

* Generalize review fixture discovery

Derive smoke cases from the leaf, domain, and paired-sample conventions so new leaves require no scoring-contract changes. Keep only exceptional selection/context overrides and fail when retrieval metadata cannot rank the selected article.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

* Preserve published field IDs in sample

Keep the existing Email and Contact Email field IDs unchanged, clarify that the sample represents an independent baseline, and use a local breaking-change rule for the generic smoke evaluation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

* Clarify published field identity rules

State explicitly that a published field keeps its ID, name, and type while a replacement is added as a separate field under an unused ID.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

* Align field obsoletion sample baselines

Use Email field ID 3 as the shared baseline so the bad example demonstrates a same-ID rename while the good example retains the original field and adds a separate replacement.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

---------

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
2026-07-15 10:55:25 +02:00

2.3 KiB

bc-version domain keywords technologies countries application-area
15..
ui
enqueuebackgroundtask
async-calculation
child-session
factbox
cue-tile
onaftergetcurrrecord
responsive-page
read-only
al
w1
all

Offload Slow Read-Only Page Calculations To Background Tasks

Description

Pages that compute statistics, aggregates, or external lookups inline block the page from rendering until the calculation finishes, producing a visible freeze on FactBoxes, cue tiles, and calculated fields. Business Central provides page background tasks: CurrPage.EnqueueBackgroundTask runs a dedicated codeunit in a read-only child session and returns values via OnPageBackgroundTaskCompleted, so the page opens immediately and fills in computed values as they arrive. This matters because users should never wait on a calculation they may not need. The mechanism has specific rules that are easy to get wrong, which is why it warrants an explicit pattern.

Best Practice

Move any noticeable read-only computation off the synchronous render path into a background task. Enqueue from OnAfterGetCurrRecord so the task is tied to the currently focused record, and pass small payloads through the Dictionary of [Text, Text] input/output, converting types with Format and Evaluate. Keep each task focused on one value or a small related set rather than one large task, and show a placeholder until results land. Because tasks auto-cancel when the page closes, the record changes, or a same-ID task is re-enqueued, always supply sensible defaults and handle the timeout path in OnPageBackgroundTaskError — never let critical functionality depend on completion. For tests, drive the task synchronously with RunPageBackgroundTask.

Anti Pattern

Enqueuing from OnAfterGetRecord on a list page fires the task for every row, and each cancels the instant the selection moves to the next row — pure wasted child-session churn; a reviewer spots EnqueueBackgroundTask called from OnAfterGetRecord (or from OnOpenPage, where the record context is not yet stable). The other tell is a task codeunit attempting a database write or Modify: background tasks run read-only and the write fails at runtime. Inline heavy calculation directly in OnAfterGetCurrRecord with no task at all is the baseline smell — it reintroduces the page freeze the feature exists to remove.