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.