Ios 在串行队列中同步异步任务
函数Ios 在串行队列中同步异步任务,ios,swift,grand-central-dispatch,Ios,Swift,Grand Central Dispatch,函数performCriticalSectionTask()可以从不同的位置多次调用。 我希望这个函数一次运行一个。因此,我将关键代码部分保留在串行异步队列中 但是,这里的问题是,关键部分本身是一个将立即返回的performLongRuningAsyncTask(),因此串行队列将不会等待当前任务首先完成,而是会启动另一个任务 如何解决此问题?如果performLongRuningAsyncTask仅在一个线程中运行,则一次只调用一次。在您的情况下,它将它委托给另一个线程,因此您将它包装到另一个
performCriticalSectionTask()
可以从不同的位置多次调用。
我希望这个函数一次运行一个。因此,我将关键代码部分保留在串行异步队列中
但是,这里的问题是,关键部分本身是一个将立即返回的performLongRuningAsyncTask()
,因此串行队列将不会等待当前任务首先完成,而是会启动另一个任务
如何解决此问题?如果performLongRuningAsyncTask
仅在一个线程中运行,则一次只调用一次。在您的情况下,它将它委托给另一个线程,因此您将它包装到另一个线程调用中是不起作用的,因为它无论如何都会在另一个线程上
您可以在方法本身中进行检查,最简单的方法是添加布尔值。(也可以在执行此方法的类中添加这些检查,并使用完成处理程序)。
另一种方法是添加调度组/信号量/锁。
如果以后仍需要执行,则应使用调度组/操作队列/信号量
let serialQueue = DispatchQueue(label: "Serial Queue")
func performCriticalSectionTask() {
serialQueue.async {
performLongRuningAsyncTask()
}
}
func performLongRuningAsyncTask() {
/// some long running task
}
这里同步的只是这个长时间运行的异步任务的调度,而不是任务的运行。有两种解决方案:您可以使长时间运行的任务同步(尽管如果不知道长时间运行的异步任务在做什么,很难说这是否明智)。您可以将此异步任务包装在自定义的、异步的、操作
子类中,只有在异步任务完成时才能完成该操作。你可以用联合收割机。如果你能给我们一个关于这个长时间运行的异步任务是什么的提示,我们可能会给你更好的建议。嘿@Rob这个长时间运行的任务是一个网络请求,我也想到了操作子类,但是对于单个网络请求来说,这太多了。如果有的话,我想做一个简单的解决方案。是的,我可能只是做操作子类。它被设计来很好地处理这个异步依赖模式。例如。顺便问一下,您是否100%确定要强制网络请求按顺序进行?当你这样做的时候,你会付出巨大的性能惩罚。在绝对需要的地方将它们按顺序排列,但尽可能使它们同时进行。
func performLongRunningAsyncTask() {
self.serialQueue.sync {
if isAlreadyRunning {
return
}
isAlreadyRunning = true
}
asyncTask { result in
self.serialQueue.sync {
self.isAlreadyRunning = false
}
}
}