Structure_Concurrency5.9.0
ThrowingDiscardingTaskGroup
A throwing discarding group that contains dynamically created child tasks.
- iOS
- 17.0+
- macOS
- 14.0+
- tvOS
- 17.0+
- watchOS
- 10.0+
@frozen struct ThrowingDiscardingTaskGroup<Failure> where Failure : Error
To create a discarding task group, call the withDiscardingTaskGroup(returning:body:)
method.
Don’t use a task group from outside the task where you created it. In most cases, the Swift type system prevents a task group from escaping like that because adding a child task to a task group is a mutating operation, and mutation operations can’t be performed from a concurrent execution context like a child task.
Task execution order
Tasks added to a task group execute concurrently, and may be scheduled in any order.
Discarding behavior
A discarding task group eagerly discards and releases its child tasks as soon as they complete. This allows for the efficient releasing of memory used by those tasks, which are not retained for future next()
calls, as would be the case with a TaskGroup
.
Cancellation behavior
A throwing discarding task group becomes cancelled in one of the following ways:
when
cancelAll
is invoked on it,when an error is thrown out of the
withThrowingDiscardingTaskGroup { ... }
closure,when the
Task
running this task group is cancelled.
But also, and uniquely in discarding task groups:
when any of its child tasks throws.
The group becoming cancelled automatically, and cancelling all of its child tasks, whenever any child task throws an error is a behavior unique to discarding task groups, because achieving such semantics is not possible otherwise, due to the missing next()
method on discarding groups. Accumulating task groups can implement this by manually polling next()
and deciding to cancelAll()
when they decide an error should cause the group to become cancelled, however a discarding group cannot poll child tasks for results and therefore assumes that child task throws are an indication of a group wide failure. In order to avoid such behavior, use a DiscardingTaskGroup
instead of a throwing one, or catch specific errors in operations submitted using addTask
Since a ThrowingDiscardingTaskGroup
is a structured concurrency primitive, cancellation is automatically propagated through all of its child-tasks (and their child tasks).
A cancelled task group can still keep adding tasks, however they will start being immediately cancelled, and may act accordingly to this. To avoid adding new tasks to an already cancelled task group, use addTaskUnlessCancelled(priority:body:)
rather than the plain addTask(priority:body:)
which adds tasks unconditionally.
For information about the language-level concurrency model that DiscardingTaskGroup
is part of, see Concurrency in The Swift Programming Language.
Citizens in _Concurrency
Members
var isCancelled: Bool
A Boolean value that indicates whether the group was canceled.
var isEmpty: Bool
A Boolean value that indicates whether the group has any remaining tasks.
func addTask(priority: TaskPriority?, operation: () async throws -> Void
) func addTaskUnlessCancelled(priority: TaskPriority?, operation: () async throws -> Void
) -> Bool func cancelAll(
) Cancel all of the remaining tasks in the group.