Hi everybody,
our team is currently developing an AppKit-based Mac application. Last week, we discovered a very irritating behaviour with detached tasks and the MainActor:
If you start a detached task which at some point performs an async call to a main actor function, the remaining part of the detached task is performed on the main thread, like in this example:
Task.detached {
print("before", Thread.isMainThread)
await self.test()
print("after", Thread.isMainThread)
}
@MainActor
func test() async {
print("inside", Thread.isMainThread)
}
which leads to the following console output:
before false
inside true
after true
I reduced this example from our real-world application project in which such a detached computational task is blocking the UI/main thread.
Interestingly, the problem does not occur if you slightly modify the code by removing the async qualifier of the test function like this:
@MainActor
func test() {
print("inside", Thread.isMainThread)
}
Then the the following console output appears:
before false
inside true
after false
The problem also disappears if you wrap the main actor access inside a separate task like this:
func test() async {
let task = Task { @MainActor in
print("inside", Thread.isMainThread)
}
await task.value
}
This also leads to the following console output:
before false
inside true
after false
I am currently puzzled by the behaviour of the first variant and consider it a bug which I also filed under FB10022919. I also created a demo Xcode project showing the problem.
I would be very happy if anybody from this forum could shed some light on what is going on here.