子类继承
@MainActor
属性,确保在主线程上同步访问所有存储的。但是,如果我不想要这种“独占访问”功能怎么办。举个例子:
class GameScene: SKScene {
var imagesToUpload = ["cat", "mouse", "dog"]
var lastUploaded = ""
func uploadAllImages() async {
await withTaskGroup(of: Void.self) { group in
for name in imagesToUpload {
group.addTask {
await self.uploadImage(of: name)
self.lastUploaded = name // << Error: Main actor-isolated property 'lastUploaded' can not be mutated from a Sendable closure
}
}
}
}
func uploadImage(of: String) async {
try! await Task.sleep(for: .seconds(1))
}
}
SKScene
继承自使用UIResponder
声明的@MainActor
。据我对这个错误的理解,一个 Sendable 闭包是一个闭包,它捕获所有 Sendable 的值,即可以安全地从多个线程访问。但是在这种情况下,我不关心多个线程同时改变这个变量的值。为了在我的测试中解决这个问题,我必须这样做:
group.addTask { @MainActor in
await self.uploadImage(of: name)
self.lastUploaded = name
}
但是我担心这样做:如果
@MainActor
闭包在主线程上运行,会不会因为上传而冻结 UI?除此之外,它也违背了使用 TaskGroup 的目的,因为所有这些上传都将在主线程上排队,这基本上会使它们由于“await”关键字而按顺序发生。
所以我的问题是,如何异步修改继承
@MainActor
属性的属性?有没有办法关闭这种独占/同步访问?
你问:
如果 @MainActor 闭包在主线程上运行,会不会因为上传而冻结 UI?
不,当你到达
await
时,主角并没有被阻止,而是任务暂停,主角可以在上传过程中自由切换到其他任务。 await
将 not 阻止主要演员。 (这与传统的阻塞式 wait
API 形成对比。)
顺便说一句,鉴于您对 Swift 并发和线程的各种问题,您可能会发现 WWDC 2021 视频Swift 并发:幕后 很有趣。它涵盖了很多关于支持 Swift 并发的线程模型(包括它的线程模型)的有用背景。它也涵盖了很多其他材料,但它可能有助于您熟悉
await
“暂停点”、“延续”等概念。