ios - 在串行队列中同步异步任务
问题描述
let serialQueue = DispatchQueue(label: "Serial Queue")
func performCriticalSectionTask() {
serialQueue.async {
performLongRuningAsyncTask()
}
}
func performLongRuningAsyncTask() {
/// some long running task
}
该函数performCriticalSectionTask()
可以从不同的地方多次调用。我希望这个函数一次运行一个。因此,我将代码的关键部分保留在串行异步队列中。
但是,这里的问题是临界区本身是一个performLongRuningAsyncTask()
会立即返回的,因此serial queue
不会等待当前任务首先完成,而是会启动另一个。
我怎么解决这个问题?
解决方案
如果performLongRuningAsyncTask
只在一个线程中运行,那么它一次只会被调用一次。在您的情况下,它将它委托给另一个线程,因此您将其包装到另一个线程调用中不起作用,因为它无论如何都会在另一个线程上
您可以在方法本身中进行检查,最简单的方法是添加一个布尔值。(或者您可以使用完成处理程序在执行此方法的类中添加这些检查)。另一种方法是添加调度组/信号量/锁。如果以后还需要执行,应该使用调度组/OperationQueue/Semaphore。
func performLongRunningAsyncTask() {
self.serialQueue.sync {
if isAlreadyRunning {
return
}
isAlreadyRunning = true
}
asyncTask { result in
self.serialQueue.sync {
self.isAlreadyRunning = false
}
}
}
推荐阅读
- javascript - 页面刷新后如何保持onclick功能
- ios - 应用重新打开时,Tableview 需要更多时间来显示数据
- marklogic - 服务器端 JavaScript (.sjs) 中的 Marklogic 光学查询获取作业失败
- ios - 连接到一个父目标的 Xcode 共享扩展如何断开连接并与另一个目标关联?
- r - gsub 用模式匹配代码而不是特定的字符串变量替换字符串
- ruby-on-rails - Rails:找不到没有 ID 的对象
- css - 填补 CSS 网格布局中的空白
- vue.js - vue.config.js 代理观察者套接字问题
- powershell - 如何关闭每个交互式 PowerShell 会话?
- sql - 在 DB2 中使用 MERGE 命令时出错