首页 > 解决方案 > 使用 swift async/await api 的 GCD 串行队列方法?

问题描述

我正在采用新的async/awaitSwift API。事情很好。目前在我的应用程序中,我使用 GCD 串行队列作为管道来强制任务串行发生。

为了在应用程序中处理一些关键模型的数据,我使用了一个可从应用程序中的任何位置访问的串行队列:

let modelQueue = DispatchQueue(label: "com.myapp.updatemodelqueue")

每当模型需要修改一些模型数据时,我都会分派到该队列:

modelQueue.async {
        // ... model updates
}

随着我所做的新async/await更改,我仍然想强制模型实际更新连续发生。因此,例如,当我从服务器导入新模型数据时,我想确保它们连续发生。

例如,我的模型中可能有一个如下所示的调用:

func updateCarModel() async {
    
    let data = await getModelFromServer()
    
    modelQueue.async {
        
        // update model
        
    }

}

但是,使用该模式编写该函数不会等待模型更新更改,因为modelQueue.async. 我不想用它modelQueue.sync来避免死锁。

因此,在观看了 WWDC 视频并查看了我以这种方式实现的文档之后,利用withCheckedContinuation

func updateCarModel() async {
    
    let data = await getModelFromServer()
    
    
    await withCheckedContinuation({ continuation in
        modelQueue.async {
            
            // update model
         
            continuation.resume()
        }
    })
    
}

然而,据我了解withCheckedContinuation,这实际上是为了让我们逐步过渡以完全采用新的async/awaitSwift API。所以,这似乎不是我应该使用的最终方法。

然后我查看了actor,但我不确定这将如何让我序列化我想在应用程序周围序列化的任何模型工作,就像我对上面显示的静态队列所做的那样。

那么,我怎样才能在应用程序周围强制执行我的模型来serially像以前一样进行模型更新,同时又完全采用新的 await/async swift API 而不使用withCheckedContinuation?

标签: swiftasync-await

解决方案


通过使模型成为一个actor,Swift 同步访问它的共享可变状态。如果模型是这样写的:

actor Model {
    var data: Data
    
    func updateModel(newData: Data) {
        data = newData
    }
}

这里的updateModel函数是同步的,调用后它的执行是不间断的。因为 Model 是一个演员,Swift 限制你把它当作你从外部调用一个异步函数来对待。您必须这样做await,这会导致您的活动线程暂停。

如果您想进行updateModel异步,则其中的代码将始终是同步的,除非您通过调用 await 显式挂起它。多个调用的执行顺序updateModel不是很确定。只要您不在updateModel块内挂起,就可以确定它们是串行执行的。updateModel在这种情况下,进行异步是没有用的。


推荐阅读