How to check if the current task is cancelled in Swift Tasks (async/await) – Swift

by
Maya Patel
async-await concurrency swift-concurrency swift-data

The Problem:

In Swift Tasks, why doesn’t the code print "cancelled" when a task is cancelled using task.cancel()? Is there a better way to check for task cancellation?

The Solutions:

Solution 1: Use non-blocking `Task.sleep` or move `test` off the main actor

Problem:
In the given code, the test function is blocking the main actor by running in a tight loop without any suspension points (i.e., no await). This prevents the task.cancel() line from being reached, resulting in the cancellation check never being performed.

Solution:
There are two ways to address this issue:

  1. Move test off the main actor:

    By marking test as nonisolated, it will no longer run on the main actor and will not block it. However, it’s important to note that blocking any thread in the Swift concurrency cooperative thread pool is generally discouraged.

  2. Use non-blocking Task.sleep:

    Instead of the tightly spinning loop, use Task.sleep with a short duration (e.g., 0.5 seconds) to introduce a suspension point. This allows the main actor to make progress and eventually execute the task.cancel() line.

Additional Considerations:

  • If test is a time-consuming spinning process, it should be moved off the main actor, periodically call try Task.checkCancellation(), and also periodically call try Task.yield().
  • For legacy cancelable API, consider using withTaskCancellationHandler to proactively stop the asynchronous process when a task is canceled.
  • Generally, relying on Task.isCancelled and manually throwing CancellationError is the most cumbersome approach, but it works.

Q&A

Why the following code doesn’t print "cancelled". Am I checking task cancellation in a wrong way?

The main actor is isolated and blocked by your while loop, so the task is never cancelled.

How can i fix the cancelation tasks in the given code

Use withTaskCancellationHandler to wrap your cancelable asynchronous process or use try Task.checkCancellation() within a loop.

What’s the most effective approch to check if the current task is cancelled?

If you are using async throws functions, most of them already support cancellation. Use that.

Video Explanation:

The following video, titled "How to Add Local Push Notifications to Your iOS App with Swift ...", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

This video provides further insights and detailed explanations related to the content discussed in the article.