Home > Mobile >  Are Tasks automatically cancelled upon return/completion in Swift?
Are Tasks automatically cancelled upon return/completion in Swift?

Time:05-23

I am a little uncertain about task cancellation in swift. My question is:

If a task reaches its return line (in this example, Line 4), does this mean it will be automatically canceled? (and thus free up memory any used thread(s) previously occupied by the Task?)

someBlock {
    Task<Bool, Never> {
        await doSomeWork()
        return true // Line 4
    }
}

As a follow-up, what if we then call .task on a SwiftUI View? Does anything change?

SomeView
    .task {
        await doSomeWork()
    }

Thank you for your time!

CodePudding user response:

If a task reaches its return line (in this example, Line 4), does this mean it will be automatically canceled

No. It means it will automatically end in good order. Cancellation of a task is very different and specialized thing. They are both ways of bringing a task to an end, but within that similarity they are effectively opposites of one another.

It does mean that the thread(s) used by the Task are now free for use, but this is not as dramatically important as it might seem, because await also frees the thread(s) used by the Task. That's the whole point of async/await; it is not thread-bound. A Task is not aligned with a single thread, the way a DispatchQueue is; to put it another way, we tend to use queue and thread as loose equivalents of one another, but with a Task, that is not at all the case.

As for what memory is released, it depends on what memory was being retained. The code given is too "pseudo" to draw any conclusions about that. But basically yes, your mental picture of this is right: a Task has a life of its own, and while it lives its code continues to retain whatever it has a strong reference to, and then when it ends (whether through finishing in good order or through cancellation) the Task's life ends (if you have not retained it elsewhere) and therefore so does whatever the Task's code is retaining.

Does anything change

The .task modifier, according to Apple, creates "an asynchronous task with a lifetime that matches that of the ... view". So I would say, yes: the Task no longer just has an independent life of its own, but rather it is being retained behind the scenes (in order that the SwiftUI framework can cancel it if the View goes out of existence), and so whatever its code has strong references to will remain.

On the other hand this might not be terribly important; it depends on whether you're using reference types. References to value types, such as a View, don't have that sort of memory management implications.

  • Related