<!--
{
  "availability" : [
    "iOS: 13.0.0 -",
    "iPadOS: 13.0.0 -",
    "macCatalyst: 13.0.0 -",
    "macOS: 10.15.0 -",
    "tvOS: 13.0.0 -",
    "visionOS: 1.0.0 -",
    "watchOS: 6.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "Swift",
  "identifier" : "/documentation/Swift/withTaskCancellationHandler(operation:onCancel:)",
  "metadataVersion" : "0.1.0",
  "role" : "Function",
  "symbol" : {
    "kind" : "Function",
    "modules" : [
      "Swift"
    ],
    "preciseIdentifier" : "s:12_Concurrency27withTaskCancellationHandler9operation8onCancelxxyYaq_YKYCXE_yyXEtYaq_YKs5ErrorR_r0_lF"
  },
  "title" : "withTaskCancellationHandler(operation:onCancel:)"
}
-->

# withTaskCancellationHandler(operation:onCancel:)

Execute an operation with a cancellation handler that’s immediately
invoked if the current task is canceled.

```
nonisolated(nonsending) func withTaskCancellationHandler<Return, Failure>(operation: nonisolated(nonsending) () async throws(Failure) -> Return, onCancel handler: sending () -> Void) async throws(Failure) -> Return where Failure : Error
```

## Parameters

`operation`

The operation to perform.

`handler`

A closure to execute on cancellation.
If the task is canceled, this closure is called at most once;
otherwise, it isn’t called.

## Discussion

This differs from the operation cooperatively checking for cancellation
and reacting to it in that the cancellation handler is *always* and
*immediately* invoked when the task is canceled. For example, even if the
operation is running code that never checks for cancellation, a cancellation
handler still runs and provides a chance to run some cleanup code:

```
await withTaskCancellationHandler {
  var sum = 0
  while condition {
    sum += 1
  }
  return sum
} onCancel: {
  // This onCancel closure might execute concurrently with the operation.
  condition.cancel()
}
```

### Execution order and semantics

The `operation` closure is always invoked, even when the
`withTaskCancellationHandler(operation:onCancel:)` method is called from a task
that was already canceled.

When `withTaskCancellationHandler(operation:onCancel:)` is used in a task that has already been
canceled, the cancellation handler will be executed
immediately before the `operation` closure gets to execute.

This allows the cancellation handler to set some external “canceled” flag
that the operation may be *atomically* checking for in order to avoid
performing any actual work once the operation gets to run.

The `operation` closure executes on the calling execution context, and doesn’t
suspend or change execution context unless code contained within the closure
does so. In other words, the potential suspension point of the
`withTaskCancellationHandler(operation:onCancel:)` never suspends by itself before
executing the operation.

If cancellation occurs while the operation is running, the cancellation
handler executes *concurrently* with the operation.

### Cancellation handlers and locks

Cancellation handlers which acquire locks must take care to avoid deadlock.
The cancellation handler may be invoked while holding internal locks
associated with the task or other tasks.  Other operations on the task, such
as resuming a continuation, may acquire these same internal locks.
Therefore, if a cancellation handler must acquire a lock, other code should
not cancel tasks or resume continuations while holding that lock.

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)