Middle · Explain · Async, callbacks and cancellation ownership

Does a static cancellation callback avoid retaining its explicit state?

Think through your answer before opening the explanation.

Memory & GC

Reveal answer and reasoning

The portable cancellation callback is static, so it cannot implicitly capture surrounding locals. Nevertheless the registration receives state explicitly and retains that state for the registration's lifetime. Static is a lexical capture restriction, not a promise of zero allocation, zero ownership or collection independence. A static delegate plus a large state object can retain just as much payload as a capturing delegate.

A CancellationTokenRegistration represents a lifecycle obligation. Disposing the registration unregisters the callback and may coordinate with callback execution. The exact concurrency contract matters when cancellation can run on another thread. Never hold an unrelated lock around disposal if the callback needs that same lock to finish. Requesting cancellation, waiting for the operation to complete and releasing the registration are separate events, and a robust design makes their order explicit.

A cancellation token is cooperative signaling. Cancelling it does not automatically remove all queued work, stop arbitrary user code, clear task results or return every rented buffer. The operation must observe the token at meaningful boundaries and release its own resources. A task that has completed may still be reachable because a list retains it, and its result or exception can retain additional state.

Conversely, removing a task from a list does not cancel the work it represents.

An async state machine's exact layout is a compiler and optimization detail. Do not claim that every local always survives every await or that a particular Release build necessarily allocates the same objects as Debug. Use the source to identify potential lifetimes, then inspect the representative compiled workload. Minimize state that crosses long waits when it is semantically unnecessary, and avoid storing completed task histories without a retention policy.

What a strong answer covers

  • Pending work can extend ownership beyond a method return.
  • A static callback avoids lexical capture but explicit state is still strongly owned.
  • Cancellation request, callback disposal and task completion are distinct events.

Common pitfall

Assuming a static callback retains no explicit state, or that requesting cancellation ends every outstanding lease.

Follow-up questions

  1. Can CancellationTokenRegistration.Dispose coordinate with a concurrently running callback?
  2. What happens to a large request state while a downstream task stays incomplete?

Self-review

Choose what to revisit. These marks are your own assessment and are separate from lesson completion.

Primary references

Open lesson and code ↗

← All interview questions