Managing Subprocesses
Coordinate parallel work across departments, services, or approval chains by creating child subprocesses through fork transitions. Without CheckAllSubprocessesCompleted and DeleteSubprocesses, every scheme that needs to wait for parallel branches or clean up active children would require custom code. These built-in actions handle subprocess lifecycle in conjunction with the scheme's fork and merge transitions.
How subprocesses work in Workflow Engine
A subprocess is a process instance that runs as a child of a parent process. Subprocesses are created through fork transitions on the scheme, not through the CreateProcess action:
- Fork transitions (
IsFork="true") withSubprocessInOutDefinition="Start"create child subprocesses that execute in parallel. - Merge transitions with
SubprocessInOutDefinition="Finalize"bring subprocesses back to the parent. CheckAllSubprocessesCompletedchecks the process tree for active children.DeleteSubprocessesdeletes all child subprocesses.
CreateProcess is a separate action that creates independent process instances without a parent-child relationship. It is not tracked by CheckAllSubprocessesCompleted or DeleteSubprocesses.
Real-world scenario: employee onboarding
A company onboarding workflow assigns tasks across three departments when a new employee joins. The parent workflow forks into three parallel subprocesses - one for IT (provision laptop), one for HR (enrollment), and one for Facilities (desk assignment). Each subprocess runs independently. The parent waits until all three subprocesses complete before marking the employee as onboarded.
Workflow scheme
The parent scheme forks into three subprocess branches. Each branch (IT_Department, HR_Department, Facilities_Department) runs as a child process. When all three merge back, CheckAllSubprocessesCompleted allows the process to finalize.

Related capabilities: CheckAllSubprocessesCompleted condition, DeleteSubprocesses action, fork/merge transitions, CreateProcess action.
<Process Name="EmployeeOnboarding" CanBeInlined="false"> <Designer /> <Commands> <Command Name="CompleteIT" /> <Command Name="CompleteHR" /> <Command Name="CompleteFacilities" /> </Commands> <Activities> <Activity Name="Start" State="Start" IsInitial="True" IsFinal="False" IsForSetState="True" IsAutoSchemeUpdate="True"> <Designer X="100" Y="300" /> </Activity> <Activity Name="LaunchTasks" State="LaunchTasks" IsInitial="False" IsFinal="False" IsForSetState="True" IsAutoSchemeUpdate="True"> <Designer X="350" Y="300" /> </Activity> <Activity Name="IT_Department" State="IT_Department" IsInitial="False" IsFinal="False" IsForSetState="True" IsAutoSchemeUpdate="True"> <Designer X="700" Y="100" /> </Activity> <Activity Name="HR_Department" State="HR_Department" IsInitial="False" IsFinal="False" IsForSetState="True" IsAutoSchemeUpdate="True"> <Designer X="700" Y="300" /> </Activity> <Activity Name="Facilities_Department" State="Facilities_Department" IsInitial="False" IsFinal="False" IsForSetState="True" IsAutoSchemeUpdate="True"> <Designer X="700" Y="500" /> </Activity> <Activity Name="Merged" State="Merged" IsInitial="False" IsFinal="False" IsForSetState="True" IsAutoSchemeUpdate="True"> <Designer X="1050" Y="300" /> </Activity> <Activity Name="Complete" State="Complete" IsInitial="False" IsFinal="True" IsForSetState="True" IsAutoSchemeUpdate="True"> <Designer X="1400" Y="200" /> </Activity> </Activities> <Transitions> <Transition Name="Start_LaunchTasks" To="LaunchTasks" From="Start" Classifier="Direct" IsFork="false" MergeViaSetState="false" DisableParentStateControl="false"> <Triggers> <Trigger Type="Auto" /> </Triggers> <Conditions> <Condition Type="Always" /> </Conditions> <Designer /> </Transition> <Transition Name="LaunchTasks_IT" To="IT_Department" From="LaunchTasks" Classifier="NotSpecified" IsFork="true" MergeViaSetState="false" DisableParentStateControl="false" SubprocessInOutDefinition="Start" SubprocessStartupType="SameThread" SubprocessStartupParameterCopyStrategy="CopyAll"> <Triggers> <Trigger Type="Auto" /> </Triggers> <Conditions> <Condition Type="Always" /> </Conditions> <Designer /> </Transition> <Transition Name="LaunchTasks_HR" To="HR_Department" From="LaunchTasks" Classifier="NotSpecified" IsFork="true" MergeViaSetState="false" DisableParentStateControl="false" SubprocessInOutDefinition="Start" SubprocessStartupType="SameThread" SubprocessStartupParameterCopyStrategy="CopyAll"> <Triggers> <Trigger Type="Auto" /> </Triggers> <Conditions> <Condition Type="Always" /> </Conditions> <Designer /> </Transition> <Transition Name="LaunchTasks_Facilities" To="Facilities_Department" From="LaunchTasks" Classifier="NotSpecified" IsFork="true" MergeViaSetState="false" DisableParentStateControl="false" SubprocessInOutDefinition="Start" SubprocessStartupType="SameThread" SubprocessStartupParameterCopyStrategy="CopyAll"> <Triggers> <Trigger Type="Auto" /> </Triggers> <Conditions> <Condition Type="Always" /> </Conditions> <Designer /> </Transition> <Transition Name="IT_Merged" To="Merged" From="IT_Department" Classifier="NotSpecified" IsFork="true" MergeViaSetState="false" DisableParentStateControl="false" SubprocessInOutDefinition="Finalize" SubprocessFinalizeParameterMergeStrategy="OverwriteAllNulls"> <Triggers> <Trigger Type="Command" NameRef="CompleteIT" /> </Triggers> <Conditions> <Condition Type="Always" /> </Conditions> <Designer /> </Transition> <Transition Name="HR_Merged" To="Merged" From="HR_Department" Classifier="NotSpecified" IsFork="true" MergeViaSetState="false" DisableParentStateControl="false" SubprocessInOutDefinition="Finalize" SubprocessFinalizeParameterMergeStrategy="OverwriteAllNulls"> <Triggers> <Trigger Type="Command" NameRef="CompleteHR" /> </Triggers> <Conditions> <Condition Type="Always" /> </Conditions> <Designer /> </Transition> <Transition Name="Facilities_Merged" To="Merged" From="Facilities_Department" Classifier="NotSpecified" IsFork="true" MergeViaSetState="false" DisableParentStateControl="false" SubprocessInOutDefinition="Finalize" SubprocessFinalizeParameterMergeStrategy="OverwriteAllNulls"> <Triggers> <Trigger Type="Command" NameRef="CompleteFacilities" /> </Triggers> <Conditions> <Condition Type="Always" /> </Conditions> <Designer /> </Transition> <Transition Name="Merged_Complete" To="Complete" From="Merged" Classifier="Direct" IsFork="false" MergeViaSetState="false" DisableParentStateControl="false"> <Triggers> <Trigger Type="Auto" /> </Triggers> <Conditions> <Condition Type="Action" NameRef="CheckAllSubprocessesCompleted" ConditionInversion="false" /> </Conditions> <Designer /> </Transition> </Transitions></Process>How the scheme works
Once the scheme is saved and BasicPlugin is registered with the WorkflowRuntime, the process runs as follows:
- Instance created - the Start activity runs and the
Autotrigger moves the process to LaunchTasks. - LaunchTasks forks - three
Auto-triggered fork transitions (SubprocessInOutDefinition="Start") create child subprocesses for IT, HR, and Facilities. Each child runs independently and in parallel. - Each subprocess waits - IT_Department, HR_Department, and Facilities_Department each wait for their respective commands (
CompleteIT,CompleteHR,CompleteFacilities). - Subprocess completes - when a command is executed on a subprocess, it transitions to Merged via
SubprocessInOutDefinition="Finalize"and terminates. - All complete - when all three subprocesses have finalized,
CheckAllSubprocessesCompletedreturnstrueon the Merged activity. TheAutotrigger moves the process to Complete and it finalizes.
Reference
BasicPlugin provides the following actions and conditions for managing subprocess lifecycles.
CheckAllSubprocessesCompleted condition
Checks whether direct child subprocesses have finished. Mode controls whether child completion alone is enough or the current parent process must also be at the merge activity. The condition uses the process instance tree maintained by the runtime.
| Parameter | Required | Default | Description |
|---|---|---|---|
Mode | Yes | AllSubprocesses | Selects whether to wait only for direct child subprocesses or for them and the current parent process at the merge activity. |
AllSubprocesses waits only for direct child subprocesses. It returns true when the current process node in ProcessInstancesTree has no active direct children.
AllSubprocessesAndParent waits for both parts of the merge: the direct child subprocesses must have finalized, and the current parent process must be at the merge activity. The runtime verifies the parent part with processInstance.ExecutedTransition.From.Name == processInstance.CurrentActivityName. Here, the parent is the current process that owns the subprocess branches, not a separate ancestor process.
DeleteSubprocesses action
Deletes all child subprocesses and their data. The action takes no parameters.
Enums
BasicPlugin uses the following enums in condition parameters.
CheckMode
The Mode parameter in CheckAllSubprocessesCompleted determines which processes are checked.
| Value | Behavior |
|---|---|
AllSubprocesses | Wait until all active direct child subprocesses have finished. |
AllSubprocessesAndParent | Wait until all direct child subprocesses have finalized and the current parent process has reached the merge activity. |
See also
Basic Plugin Overview
Registration, configuration, and full API reference.
Subprocesses
How subprocesses work in Workflow Engine.
Process Control
Jump between activities and control process state.
Parallel Approval
Set up multi-user approval without explicit branches.
Frequently asked questions
What is the difference between subprocesses and CreateProcess?
Subprocesses are created through fork transitions with SubprocessInOutDefinition="Start". They are tracked in the process tree and CheckAllSubprocessesCompleted checks them. The CreateProcess action creates an independent process instance that is not tracked as a subprocess.
How do I create parallel subprocesses?
Add multiple fork transitions from the same activity with IsFork="true", SubprocessInOutDefinition="Start", and distinct target activities. Each becomes a child subprocess.
How do I wait for all subprocesses to complete?
Add CheckAllSubprocessesCompleted as a condition on the merge transition. With Mode="AllSubprocesses", it returns true when all direct child subprocesses have finalized. With Mode="AllSubprocessesAndParent", the current process must also be at the merge activity.
How do I cancel subprocesses?
Use the DeleteSubprocesses action to remove all child processes. Add it to an activity implementation and transition to a cancellation state.