elsa-workflows / elsa-workflows/elsa-core
Execution behavior between ForEach and ParallelForEach activity bodies differs
- Dominant language
- C#
- Stars
- 7.9k
- Forks
- 1.5k
- Avg merge
- 15h 22m
- Merged PRs (30d)
- 114
Description
## *Description:*
In elsa 3.3+, when using the ParallelForEach activity, the execution behavior of the activities inside the Body differs from that of the standard ForEach.
In ForEach, each item is processed sequentially, and all activities within the body are executed for each item before moving to the next.
However, in ParallelForEach, instead of executing the full set of body activities for each item in parallel, it appears to execute the first activity in the body across all items, then the second activity across all items, and so on — as if the body activities are being batched rather than grouped per item.
This behavior breaks expected item-level processing logic and makes it difficult to use ParallelForEach as a drop-in replacement for ForEach in scenarios requiring parallelism.
Expected Behavior:
Each item should execute all body activities in parallel, independently from other items.
**Attachments**:
```yaml
- id: Act4
name: Activity 4
type: Elsa.ForEach # Elsa.ParallelForEach
items:
typeName: List
expression:
type: CSharp
value: |
new List { "i0","i1", "i2", "i3", "i4" }
currentValue:
typeName: Object
memoryReference:
id: v1
body:
id: Act5
type: Elsa.Flowchart
customProperties:
runAsynchronously: true
variables:
- id: v2
name: IterationItem
typeName: Object
isArray: false
storageDriverTypeName: 'Elsa.Workflows.MemoryStorageDriver, Elsa.Workflows.Core'
activities:
- id: Act6
type: Elsa.WriteLine
text:
typeName: Object
expression:
type: CSharp
value: Variable.GetCurrentIndex("Act5")
- id: Act7
type: Elsa.SetVariable
variable:
id: v2
value:
typeName: String
expression:
type: CSharp
value: |
Variable.GetCurrentValue("Act5")
- id: Act8
type: Elsa.WriteLine
text:
typeName: Object
expression:
type: CSharp
value: |
Variable.Get("IterationItem")
connections:
- source:
activity: Act6
port: Done
target:
activity: Act7
port: In
- source:
activity: Act7
port: Done
target:
activity: Act8
port: In
```
4. **Reproduction Rate**: "every time"
5. **Video/Screenshots**:
ForEach: result
0
i0
1
i1
2
i2
3
i3
4
i4
ParallelForEach: result
0
1
2
3
4
i0
i1
i2
i3
i4
6. **Additional Configuration**:
extension added for getting current iteration context values
```cs
public static class ContextExtensions
{
public static TValue GetIterationValue(this object context, string activityId, string variableName)
{
ActivityExecutionContext? activityExecutionContext = GetActivityContext(context, activityId);
var currentItem = activityExecutionContext
.GetVariable(variableName);
if (currentItem == null)
{
throw new InvalidOperationException($"{variableName} property not found.");
}
return currentItem;
}
private static ActivityExecutionContext? GetActivityContext(object context, string activityId)
{
var executionContextInfo = context.GetType().GetProperty("ExecutionContext");
if (executionContextInfo == null)
{
throw new InvalidOperationException("ExecutionContext property not found.");
}
var proxy = executionContextInfo.GetValue(context) as ExecutionContextProxy;
var currentExecutionContext = proxy.ExpressionExecutionContext.GetActivityExecutionContext();
var activityExecutionContext = currentExecutionContext.GetAncestors()
.FirstOrDefault(x => x.Activity.Id == activityId);
return activityExecutionContext;
}
}
```
## Expected Behavior
in ParallelForEach, entire body activities execute in group, but the group may occur in random order as below:
2
i2
0
i0
1
i1
4
i4
3
i3
elsa version: 3.3
Please clarify the understanding for this scenario. Thanks.
Contributor guide
Research direction
Start by reproducing the YAML example with ForEach and ParallelForEach, focusing on the ParallelForEach activity and its Flowchart body. Compare the observed output with the expected item-grouped execution, allowing item groups to complete in any order; done means each item's full body runs together rather than activity stages being batched across items.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100