【问题标题】:GCD serial queue like approach using swift async/await api?使用 swift async/await api 的 GCD 串行队列方法?
【发布时间】:2021-09-28 22:34:47
【问题描述】:

我正在采用新的async/await Swift 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/await Swift API。所以,这似乎不是我应该使用的最终方法。

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

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

【问题讨论】:

  • Actor 正是这样做的,允许您在 async-await 范式中对某些模型对象执行异步更新,但无需您手动与串行队列(或任何其他普通同步机制)同步。它会为您进行同步。
  • 是的,我同意。我只是想了解我将如何正确地构建事物。是全球演员吗?队列的好处是,我可以从应用程序的任何地方调度它并完成。所以,这就是我研究演员的原因,但不确定如何实际解决它以提供与应用程序范围的串行队列类似的方法......
  • 使用actor的问题是你只能在actor上使用非异步函数来创建串行队列。如果您使用标记为 async 的函数,则其他代码可以在暂停期间运行,这使其成为非串行的。
  • 我也有类似的问题。在幕后的并发演讲中,他们有一个使用 Actor 代替串行数据库队列的示例。但他们指出,Actor 调用不再有发生前/FIFO 保证,这与串行队列(调度或操作)不同。

标签: swift async-await


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2012-12-17
    • 1970-01-01
    • 2022-08-23
    • 1970-01-01
    • 2016-06-04
    • 2013-10-11
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    相关资源
    最近更新 更多