I have read some articles and have been told that if an async function only contains normal synchronous code, then there won't be a suspension during runtime, no switching thread, as this article mentioned
If a suspension does not happen, no pause will take place and your function will continue to run with the same efficiency and timings as a synchronous function. That last part carries an important side effect: using await will not cause your code to wait for one runloop to go by before continuing.
However I did a test and it seems doesn't work that way
struct ContentStructure: View {
var body: some View {
CustomView()
.task {
print("task start thread = \(Thread.current)")
await fakeExpensiveWork()
print("task end thread = \(Thread.current)")
}
}
}
func fakeExpensiveWork() async {
print("fake expensive work thread = \(Thread.current)")
}
struct CustomView: View{
init(){
print("init thread = \(Thread.current)")
}
var body: some View{
List{
ForEach(1..<100){ _ in
Text("Hello, world!")
}
}
}
}
printed:
init thread = <_NSMainThread: 0x600001704000>{number = 1, name = main}
task start thread = <_NSMainThread: 0x600001704000>{number = 1, name = main}
fake expensive work thread = <NSThread: 0x60000176ae00>{number = 6, name = (null)}
task end thread = <_NSMainThread: 0x600001704000>{number = 1, name = main}
Compiled with: Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4) Target: arm64-apple-darwin23.6.0
As the log showed, it always switch a thread to do the fakeExpensiveWork()
even if it just print a log. When I put Thread.sleep(forTimeInterval: 10)
inside the fakeExpensiveWork
, the List
still can be scrolled smoothly.
So is my understanding of this article incorrect, or has Apple updated the behavior of Swift?
Because fakeExpensiveWork
doesn't bound to any Actor so when it is called, your code is submit to global concurrent Excutor
, then it will submit job to coorperative pool
which is a group of thread managed so it depends on coorperative pool
to assign your job to a particular thread, therefore we can not exactly know which thread your code is running ( a special case is MainActor
when we know that our code is run on Main Thread
). Take a look at this excellent blog for more explain