For what reason we want to use Task { ... }
initializer instead of Task.detached { ... }
?
Because the Task { ... }
as I understand always bring us at world of serialize instead world of parallelism, and all tasks that we initialize (in ViewController) in this way are executed on the main thread and hang an applications. And even a posting work on main thread made via Task.detached in the docs
Task.detached { @MainActor in
// ...
}
(https://github.com/apple/swift-evolution/blob/main/proposals/0316-global-actors.md)
I mean, why was this way of initializing tasks made, what could such an initializer be useful for? Can you post any useful examples of such manner of initialization a Task?
More specifically, why would we need the ability
- inherit the actor's execution context and run the task on its executor, rather than the global concurrent one
?
Sorry, partly found the answer to the question in the last post of that topic When does a Task get scheduled to the Cooperative Thread Pool? - #4 by rayaantaneja
func someSyncWork() {}
func someAsyncWork() async {}
@MainActor
func someMainWork() async {}
...
func viewDidLoad() {
super.viewDidLoad()
Task {
someSyncWork() // Executed on main actor due to Task capturing actor context by default.
await someAsyncWork() // Executed on the global executor because someAsyncWork doesn't specify an actor context.
await someMainWork() // Executed on main actor because it specifies main actor.
}
}
So I made an example and it works fine
@MainActor
class MainThreadLock: ObservableObject {
@Published var text = "-"
func run() {
Task {
let k = await someParallelWork()
text.append("\(k)")
}
}
}
func someParallelWork() async -> Double {
let a = Array(0...10000000)
return a.reduce(0.0) { partialResult, z in
partialResult + Double(z) / 2
}
}
The main thread does not hang, because the someParallelWork()
being executed in global thread pool.