Header menu logo Mibo

HeadlessRunner<'Model, 'Msg> Type

Controls execution of a headless Elmish program with explicit frame stepping.

The runner delegates message processing to a shared ElmishLoop and adds observer notification + virtual time management on top. Call Step or StepN to advance the simulation.

Constructors

Constructor Description

HeadlessRunner(program, ?width, ?height)

Full Usage: HeadlessRunner(program, ?width, ?height)

Parameters:
Returns: HeadlessRunner<'Model, 'Msg>
program : HeadlessProgram<'Model, 'Msg>
?width : int
?height : int
Returns: HeadlessRunner<'Model, 'Msg>

Instance members

Instance member Description

this.Dispatch

Full Usage: this.Dispatch

Parameters:
    msg : 'Msg

Dispatch a message to the runner.

msg : 'Msg

this.DispatchMany

Full Usage: this.DispatchMany

Parameters:
    msgs : 'Msg seq

Dispatch multiple messages at once.

msgs : 'Msg seq

this.Dispose

Full Usage: this.Dispose

Dispose active subscriptions, observers, and clean up resources.

this.GameTime

Full Usage: this.GameTime

Returns: GameTime

Total elapsed virtual time.

Returns: GameTime

this.Model

Full Usage: this.Model

Returns: 'Model

The current model state.

Returns: 'Model

this.Run

Full Usage: this.Run

Parameters:
    interval : TimeSpan - Tick interval (e.g. TimeSpan.FromMilliseconds(16) for 60fps).
    ?ct : CancellationToken - Optional cancellation token to stop the loop early.

Returns: (GameTime * 'Model) seq A sequence of (GameTime * 'Model) snapshots, paced by the interval.

Run the simulation synchronously, yielding each frame as a sequence.

Uses a spin-wait with Thread.Sleep(1) to pace the loop. This is the standard pattern for game servers — the Stopwatch controls timing precision while Sleep yields the CPU between ticks.

This advances the runner's internal state. Do not mix with Step/StepN/StepUntil on the same runner — they all advance the simulation and using them together will produce simulation corruption.

interval : TimeSpan

Tick interval (e.g. TimeSpan.FromMilliseconds(16) for 60fps).

?ct : CancellationToken

Optional cancellation token to stop the loop early.

Returns: (GameTime * 'Model) seq

A sequence of (GameTime * 'Model) snapshots, paced by the interval.

this.RunAsync

Full Usage: this.RunAsync

Parameters:
Returns: IAsyncEnumerable<GameTime * 'Model> An async sequence of (GameTime * 'Model) snapshots.

Run the simulation asynchronously, yielding each frame as an async enumerable.

Uses PeriodicTimer for efficient, precise pacing. The for .. in syntax in F# 8+ can iterate over IAsyncEnumerable directly.

This advances the runner's internal state. Do not mix with Step/StepN/StepUntil on the same runner — they all advance the simulation and using them together will produce simulation corruption.

interval : TimeSpan

Tick interval.

?ct : CancellationToken

Cancellation token to stop the loop.

Returns: IAsyncEnumerable<GameTime * 'Model>

An async sequence of (GameTime * 'Model) snapshots.

this.ShouldQuit

Full Usage: this.ShouldQuit

Returns: bool

Whether the runner has received a Quit signal.

Returns: bool

this.Step

Full Usage: this.Step

Parameters:
    elapsed : TimeSpan - Frame delta (e.g. TimeSpan.FromMilliseconds(16) for 60fps). Negative values are clamped to zero.

Advance the simulation by one frame with the given delta time.

This mutates the runner's internal state (model, game time, subscriptions, deferred commands). Do not mix Step/StepN/StepUntil with Run/RunAsync on the same runner — they all advance the simulation and using them together will produce simulation corruption.

elapsed : TimeSpan

Frame delta (e.g. TimeSpan.FromMilliseconds(16) for 60fps). Negative values are clamped to zero.

this.StepN

Full Usage: this.StepN

Parameters:
    count : int - Number of frames to run.
    elapsed : TimeSpan - Frame delta per step.

Advance the simulation by N frames.

This mutates the runner's internal state. Do not mix with Run/RunAsync on the same runner — they all advance the simulation and using them together will produce simulation corruption.

count : int

Number of frames to run.

elapsed : TimeSpan

Frame delta per step.

this.StepUntil

Full Usage: this.StepUntil

Parameters:
    predicate : 'Model -> bool - Condition to check after each frame.
    elapsed : TimeSpan - Frame delta per step.
    ?maxFrames : int - Safety limit to prevent infinite loops.

Returns: bool True if predicate was met, false if maxFrames was reached.

Advance until a predicate on the model returns true.

This mutates the runner's internal state. Do not mix with Run/RunAsync on the same runner — they all advance the simulation and using them together will produce simulation corruption.

predicate : 'Model -> bool

Condition to check after each frame.

elapsed : TimeSpan

Frame delta per step.

?maxFrames : int

Safety limit to prevent infinite loops.

Returns: bool

True if predicate was met, false if maxFrames was reached.

Type something to start searching.