Skip to content

5.5.2.2.2. Control Flow

Mikołaj Milewski edited this page Nov 12, 2026 · 1 revision

Control Flow

A control flow carries execution permission from one node to another without carrying an application token. It corresponds to the solid-line control flow in a UML Activity Diagram. Add it from the source node using AddControlFlow(...).

Defining control flows

.AddInitial(node => node
    .AddControlFlow("ReserveInventory"))
.AddAction(
    "ReserveInventory",
    async c => await inventory.ReserveAsync(orderId, c.CancellationToken),
    node => node.AddControlFlow("PackOrder"))
.AddAction(
    "PackOrder",
    async c => await shipping.PackAsync(orderId, c.CancellationToken),
    node => node.AddControlFlow<FinalNode>())
.AddFinal()

AddControlFlow<TTargetNode>() uses the target node type's Stateflows name; the string overload is useful for lambda-defined nodes. Control-flow guards can restrict traversal. Control flows are also used by Initial, Final, Decision, Fork, Join, and Merge nodes; they do not make values available through GetTokensOfType<T>().

All Activity node names are globally unique. Ordinary node names supplied by the builder are used as-is; initial and typed input boundary names are scope-qualified, while output pins and final nodes have configurable names. AddControlFlow("name") resolves that registered name; when the target is outside the source's containing scope, Stateflows routes the flow as a crossing automatically. Ordinary structured scopes allow both crossing directions, but incoming offers never start their destination scopes and cannot cross into reentrant structures. Parallel/iterative boundaries allow outgoing crossings only to their immediate parent scope. See Crossing structured boundaries for activation, cancellation, and checkpoint ownership.

Use Data Flow for values and Flows for guards and transformations shared by flow kinds.

Clone this wiki locally