WorkRunner
Internal work queue that collects and executes WorkRequest continuations. Each WorkRunner instance is associated with a specific Unity update phase (Update, LateUpdate, FixedUpdate, or Editor Update) inside the ParagonSynchronizationContext. When the corresponding phase fires in the PlayerLoop, the runner drains its queue and invokes all pending continuations on the main thread.
Definition
Namespace: Paragon.Core.Async Assembly: Paragon.dll
internal class WorkRunnerRemarks
WorkRunner is the execution backbone of the ParagonSynchronizationContext. The synchronization context owns multiple runners — one per WorkExecutionTime value — and routes incoming continuations to the appropriate runner based on the requested execution time.
When Run() is called (triggered by the PlayerLoop at the correct update phase), the runner processes only the requests that were queued before Run() began. Any new requests added during execution (e.g., by continuations that await again) are deferred to the next frame's run. This is achieved by capturing the queue count before the loop starts.
The initial queue capacity is 20, chosen to minimize allocations during typical frame workloads.
Quick Lookup
Queue a continuation
runner.Add(workRequest)
Execute all pending work
runner.Run()
Discard all pending work
runner.Clear()
Constructor
WorkRunner()
Creates a new runner with an empty queue (initial capacity of 20).
Methods
Add
Enqueues a WorkRequest for execution on the next Run() call.
workRequest
WorkRequest
The work item containing the continuation to execute
Clear
Discards all pending work requests from the queue.
Run
Dequeues and invokes all currently pending work requests. Only processes requests that were in the queue when Run() was called — requests added during execution are left for the next cycle.
Common Pitfalls
Continuations added during Run() are deferred If a continuation enqueues more work (e.g., via another await Yield.WaitForUpdate()), that new request will not execute in the same Run() cycle. It will be picked up in the next frame's run. This is intentional and prevents infinite loops.
See Also
ParagonSynchronizationContext — owns and drives the runners
YieldAwaitable — posts continuations to the context, which routes to the correct runner
SynchronizationContext Subsystem — subsystem overview
Last updated