如何在继承@MainActor时异步修改MainActor隔离的属性

问题描述 投票:0回答:1

子类继承

@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
属性的属性?有没有办法关闭这种独占/同步访问?

ios swift inheritance concurrency actor
1个回答
1
投票

你问:

如果 @MainActor 闭包在主线程上运行,会不会因为上传而冻结 UI?

不,当你到达

await
时,主角并没有被阻止,而是任务暂停,主角可以在上传过程中自由切换到其他任务。
await
not 阻止主要演员。 (这与传统的阻塞式
wait
API 形成对比。)


顺便说一句,鉴于您对 Swift 并发和线程的各种问题,您可能会发现 WWDC 2021 视频Swift 并发:幕后 很有趣。它涵盖了很多关于支持 Swift 并发的线程模型(包括它的线程模型)的有用背景。它也涵盖了很多其他材料,但它可能有助于您熟悉

await
“暂停点”、“延续”等概念。

© www.soinside.com 2019 - 2024. All rights reserved.