Class WhenAllExtensionsAsync
- Namespace
- Trellis
- Assembly
- Trellis.Core.dll
Provides Await extension methods for waiting on multiple Task-wrapped Result instances and combining them. These methods enable efficient parallel execution of independent async operations with Result aggregation.
public static class WhenAllExtensionsAsync
- Inheritance
-
WhenAllExtensionsAsync
- Inherited Members
Examples
// Execute three independent async operations in parallel
var result = await (
GetUserAsync(userId),
GetOrdersAsync(userId),
GetPreferencesAsync(userId)
).WhenAllAsync();
// All three operations run concurrently
// If all succeed, result contains (user, orders, preferences)
// If any fail, result contains all errors
// Then process the combined result
result.Match(
onSuccess: (user, orders, prefs) => ProcessData(user, orders, prefs),
onFailure: error => HandleError(error)
);
Remarks
WhenAllAsync waits for all tasks to complete using Task.WhenAll for efficient parallel execution, then combines their results using the standard Combine semantics.
These overloads expect each task to complete with a Result<TValue>. If a task faults or is canceled,
the exception escapes from Task.WhenAll instead of being converted into a failed result.
Key characteristics:
- All tasks execute in parallel (not sequentially)
- Waits for all tasks to complete before combining results
- If any task's result fails, all errors are aggregated
- Faulted or canceled tasks propagate their exception to the caller
- More efficient than sequential await chains for independent operations
- Creates distributed tracing spans for observability
Use WhenAllAsync when you need to:
- Execute multiple independent async operations in parallel
- Wait for all operations to complete before proceeding
- Combine results from parallel operations
- Maximize throughput for I/O-bound operations
- Monitor parallel operation performance in distributed traces
Methods
WhenAllAsync<T1, T2>((Task<Result<T1>>, Task<Result<T2>>))
Awaits two parallel async Result operations and combines their results.
public static Task<Result<(T1, T2)>> WhenAllAsync<T1, T2>(this (Task<Result<T1>>, Task<Result<T2>>) tasks)
Parameters
Returns
- Task<Result<(T1, T2)>>
A task that represents the asynchronous operation. The task result contains:
- A success result with a 2-element tuple if both tasks succeed
- A failure result with combined errors if either task fails
Type Parameters
T1The type of the first result value.
T2The type of the second result value.
Examples
var result = await (
GetUserAsync(userId),
GetOrdersAsync(userId)
).WhenAllAsync();
result.Match(
onSuccess: (user, orders) => ProcessUser(user, orders),
onFailure: error => LogError(error)
);
Remarks
This method uses Task.WhenAll to execute both operations in parallel, then combines their results using standard Combine semantics. If either task faults or is canceled, that exception escapes immediately. Creates a distributed tracing span to monitor parallel execution.
WhenAllAsync<T1, T2, T3>((Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>))
Awaits 3 parallel async Result operations and combines their results.
public static Task<Result<(T1, T2, T3)>> WhenAllAsync<T1, T2, T3>(this (Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>) tasks)
Parameters
tasks(Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>)A tuple containing 3 tasks that produce Result values.
Returns
- Task<Result<(T1, T2, T3)>>
A task that represents the asynchronous operation. The task result contains:
- A success result with a 3-element tuple if all tasks succeed
- A failure result with combined errors if any task fails
Type Parameters
T1The type of the first result value.
T2The type of the second result value.
T3The type of the third result value.
Examples
var result = await (
GetUserAsync(id),
GetOrdersAsync(id),
GetPreferencesAsync(id) /// ).WhenAllAsync();
result.Bind((v1, v2, v3) => Process(v1, v2, v3));
Remarks
All 3 tasks execute in parallel using Task.WhenAll for maximum efficiency. Results are combined only after all tasks complete. If any task faults or is canceled, that exception escapes immediately. Creates a distributed tracing span to monitor parallel execution.
This is significantly more efficient than:
var r1 = await Task1(); // Wait
var r2 = await Task2(); // Wait
var r3 = await Task3(); // Wait sequentially
WhenAllAsync<T1, T2, T3, T4>((Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>))
Awaits 4 parallel async Result operations and combines their results.
public static Task<Result<(T1, T2, T3, T4)>> WhenAllAsync<T1, T2, T3, T4>(this (Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>) tasks)
Parameters
tasks(Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>)A tuple containing 4 tasks that produce Result values.
Returns
- Task<Result<(T1, T2, T3, T4)>>
A task that represents the asynchronous operation. The task result contains:
- A success result with a 4-element tuple if all tasks succeed
- A failure result with combined errors if any task fails
Type Parameters
T1The type of the first result value.
T2The type of the second result value.
T3The type of the third result value.
T4The type of the fourth result value.
Examples
var result = await (
GetUserAsync(id),
GetOrdersAsync(id),
GetPreferencesAsync(id),
GetData4Async(id) /// ).WhenAllAsync();
result.Bind((v1, v2, v3, v4) => Process(v1, v2, v3, v4));
Remarks
All 4 tasks execute in parallel using Task.WhenAll for maximum efficiency. Results are combined only after all tasks complete. If any task faults or is canceled, that exception escapes immediately. Creates a distributed tracing span to monitor parallel execution.
This is significantly more efficient than:
var r1 = await Task1(); // Wait
var r2 = await Task2(); // Wait
var r3 = await Task3(); // Wait sequentially
WhenAllAsync<T1, T2, T3, T4, T5>((Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>))
Awaits 5 parallel async Result operations and combines their results.
public static Task<Result<(T1, T2, T3, T4, T5)>> WhenAllAsync<T1, T2, T3, T4, T5>(this (Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>) tasks)
Parameters
tasks(Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>)A tuple containing 5 tasks that produce Result values.
Returns
- Task<Result<(T1, T2, T3, T4, T5)>>
A task that represents the asynchronous operation. The task result contains:
- A success result with a 5-element tuple if all tasks succeed
- A failure result with combined errors if any task fails
Type Parameters
T1The type of the first result value.
T2The type of the second result value.
T3The type of the third result value.
T4The type of the fourth result value.
T5The type of the fifth result value.
Examples
var result = await (
GetUserAsync(id),
GetOrdersAsync(id),
GetPreferencesAsync(id),
GetData4Async(id),
GetData5Async(id) /// ).WhenAllAsync();
result.Bind((v1, v2, v3, v4, v5) => Process(v1, v2, v3, v4, v5));
Remarks
All 5 tasks execute in parallel using Task.WhenAll for maximum efficiency. Results are combined only after all tasks complete. If any task faults or is canceled, that exception escapes immediately. Creates a distributed tracing span to monitor parallel execution.
This is significantly more efficient than:
var r1 = await Task1(); // Wait
var r2 = await Task2(); // Wait
var r3 = await Task3(); // Wait sequentially
WhenAllAsync<T1, T2, T3, T4, T5, T6>((Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>))
Awaits 6 parallel async Result operations and combines their results.
public static Task<Result<(T1, T2, T3, T4, T5, T6)>> WhenAllAsync<T1, T2, T3, T4, T5, T6>(this (Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>) tasks)
Parameters
tasks(Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>)A tuple containing 6 tasks that produce Result values.
Returns
- Task<Result<(T1, T2, T3, T4, T5, T6)>>
A task that represents the asynchronous operation. The task result contains:
- A success result with a 6-element tuple if all tasks succeed
- A failure result with combined errors if any task fails
Type Parameters
T1The type of the first result value.
T2The type of the second result value.
T3The type of the third result value.
T4The type of the fourth result value.
T5The type of the fifth result value.
T6The type of the sixth result value.
Examples
var result = await (
GetUserAsync(id),
GetOrdersAsync(id),
GetPreferencesAsync(id),
GetData4Async(id),
GetData5Async(id),
GetData6Async(id) /// ).WhenAllAsync();
result.Bind((v1, v2, v3, v4, v5, v6) => Process(v1, v2, v3, v4, v5, v6));
Remarks
All 6 tasks execute in parallel using Task.WhenAll for maximum efficiency. Results are combined only after all tasks complete. If any task faults or is canceled, that exception escapes immediately. Creates a distributed tracing span to monitor parallel execution.
This is significantly more efficient than:
var r1 = await Task1(); // Wait
var r2 = await Task2(); // Wait
var r3 = await Task3(); // Wait sequentially
WhenAllAsync<T1, T2, T3, T4, T5, T6, T7>((Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>, Task<Result<T7>>))
Awaits 7 parallel async Result operations and combines their results.
public static Task<Result<(T1, T2, T3, T4, T5, T6, T7)>> WhenAllAsync<T1, T2, T3, T4, T5, T6, T7>(this (Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>, Task<Result<T7>>) tasks)
Parameters
tasks(Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>, Task<Result<T7>>)A tuple containing 7 tasks that produce Result values.
Returns
- Task<Result<(T1, T2, T3, T4, T5, T6, T7)>>
A task that represents the asynchronous operation. The task result contains:
- A success result with a 7-element tuple if all tasks succeed
- A failure result with combined errors if any task fails
Type Parameters
T1The type of the first result value.
T2The type of the second result value.
T3The type of the third result value.
T4The type of the fourth result value.
T5The type of the fifth result value.
T6The type of the sixth result value.
T7The type of the seventh result value.
Examples
var result = await (
GetUserAsync(id),
GetOrdersAsync(id),
GetPreferencesAsync(id),
GetData4Async(id),
GetData5Async(id),
GetData6Async(id),
GetData7Async(id) /// ).WhenAllAsync();
result.Bind((v1, v2, v3, v4, v5, v6, v7) => Process(v1, v2, v3, v4, v5, v6, v7));
Remarks
All 7 tasks execute in parallel using Task.WhenAll for maximum efficiency. Results are combined only after all tasks complete. If any task faults or is canceled, that exception escapes immediately. Creates a distributed tracing span to monitor parallel execution.
This is significantly more efficient than:
var r1 = await Task1(); // Wait
var r2 = await Task2(); // Wait
var r3 = await Task3(); // Wait sequentially
WhenAllAsync<T1, T2, T3, T4, T5, T6, T7, T8>((Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>, Task<Result<T7>>, Task<Result<T8>>))
Awaits 8 parallel async Result operations and combines their results.
public static Task<Result<(T1, T2, T3, T4, T5, T6, T7, T8)>> WhenAllAsync<T1, T2, T3, T4, T5, T6, T7, T8>(this (Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>, Task<Result<T7>>, Task<Result<T8>>) tasks)
Parameters
tasks(Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>, Task<Result<T7>>, Task<Result<T8>>)A tuple containing 8 tasks that produce Result values.
Returns
- Task<Result<(T1, T2, T3, T4, T5, T6, T7, T8)>>
A task that represents the asynchronous operation. The task result contains:
- A success result with a 8-element tuple if all tasks succeed
- A failure result with combined errors if any task fails
Type Parameters
T1The type of the first result value.
T2The type of the second result value.
T3The type of the third result value.
T4The type of the fourth result value.
T5The type of the fifth result value.
T6The type of the sixth result value.
T7The type of the seventh result value.
T8The type of the eighth result value.
Examples
var result = await (
GetUserAsync(id),
GetOrdersAsync(id),
GetPreferencesAsync(id),
GetData4Async(id),
GetData5Async(id),
GetData6Async(id),
GetData7Async(id),
GetData8Async(id) /// ).WhenAllAsync();
result.Bind((v1, v2, v3, v4, v5, v6, v7, v8) => Process(v1, v2, v3, v4, v5, v6, v7, v8));
Remarks
All 8 tasks execute in parallel using Task.WhenAll for maximum efficiency. Results are combined only after all tasks complete. If any task faults or is canceled, that exception escapes immediately. Creates a distributed tracing span to monitor parallel execution.
This is significantly more efficient than:
var r1 = await Task1(); // Wait
var r2 = await Task2(); // Wait
var r3 = await Task3(); // Wait sequentially
WhenAllAsync<T1, T2, T3, T4, T5, T6, T7, T8, T9>((Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>, Task<Result<T7>>, Task<Result<T8>>, Task<Result<T9>>))
Awaits 9 parallel async Result operations and combines their results.
public static Task<Result<(T1, T2, T3, T4, T5, T6, T7, T8, T9)>> WhenAllAsync<T1, T2, T3, T4, T5, T6, T7, T8, T9>(this (Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>, Task<Result<T7>>, Task<Result<T8>>, Task<Result<T9>>) tasks)
Parameters
tasks(Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>, Task<Result<T5>>, Task<Result<T6>>, Task<Result<T7>>, Task<Result<T8>>, Task<Result<T9>>)A tuple containing 9 tasks that produce Result values.
Returns
- Task<Result<(T1, T2, T3, T4, T5, T6, T7, T8, T9)>>
A task that represents the asynchronous operation. The task result contains:
- A success result with a 9-element tuple if all tasks succeed
- A failure result with combined errors if any task fails
Type Parameters
T1The type of the first result value.
T2The type of the second result value.
T3The type of the third result value.
T4The type of the fourth result value.
T5The type of the fifth result value.
T6The type of the sixth result value.
T7The type of the seventh result value.
T8The type of the eighth result value.
T9The type of the ninth result value.
Examples
var result = await (
GetUserAsync(id),
GetOrdersAsync(id),
GetPreferencesAsync(id),
GetData4Async(id),
GetData5Async(id),
GetData6Async(id),
GetData7Async(id),
GetData8Async(id),
GetData9Async(id) /// ).WhenAllAsync();
result.Bind((v1, v2, v3, v4, v5, v6, v7, v8, v9) => Process(v1, v2, v3, v4, v5, v6, v7, v8, v9));
Remarks
All 9 tasks execute in parallel using Task.WhenAll for maximum efficiency. Results are combined only after all tasks complete. If any task faults or is canceled, that exception escapes immediately. Creates a distributed tracing span to monitor parallel execution.
This is significantly more efficient than:
var r1 = await Task1(); // Wait
var r2 = await Task2(); // Wait
var r3 = await Task3(); // Wait sequentially