Hello, I have a next code and I have an error on Task B Mutation of captured var 'z' in concurrently-executing code.
static func main() async {
var z = 1
let r = Task { // Task A
z = 4
return 0
}
let k = Task.detached() { // Task B
z = 4 // Mutation of captured var 'z' in concurrently-executing code
return 0
}
let m = await k.value
print("n z: \(z)")
}
Please, explain, why there is no error in Task A. Because, it is also executed in parallel with the main()
function and it has a concurrently-executing code🤯
3 Likes
Please, explain, why there is no error in Task A.
The main
function is implicitly @MainActor
(when contained in an @main
type). Task A inherits the actor context of the caller, so it's @MainActor
as well.
This means that the calling function and Task A are not actually executing in parallel.
The detached Task on the other hand does not inherit the actor context. It is executing in parallel and thus can't safely access z
.
4 Likes
Thank you.
Please, tell
class TestController: UIViewController {
override func viewDidLoad() {
Task { // Task A
return 0
}
}
}
class TestController: UIViewController {
var z = 0
let button = UIButton(type: .close)
override func viewDidLoad() {
view.addSubview(button)
button.addTarget(self, action: #selector(tap), for: .touchUpInside)
}
@objc func tap() {
Task { // Task A
z = 4
return 0
}
}
}
The 'Task A' will be executed in parallel with the main thread, will not be executed at all, or will be executed on the main thread after all operations (started by last user input) have been completed?
As you can see from its declaration UIViewController
is @MainActor:
@MainActor class UIViewController : UIResponder
Both "Task A" examples inherit @MainActor from their surrounding actor context. Both tasks are executing on the main thread.
after all operations (started by last user input) have been completed?
That depends on what you call "operations":
-
Yes, currently executing non-async code will continue to execute before any other task can run on the main thread. (Tasks use cooperative multitasking.)
-
No, if the "operation" on the main thread is async
, it might be interrupted at an await
and your Task might run before the operation finishes.
Since your code is not async
it can't be interrupted.
1 Like
And if we started our task on main thread and it is waiting a big download task now, could an user input interrupt its waiting and revive the main thread?
Not sure what you're asking but this does not block the main thread: UI is still responsive.
1 Like