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
     }
   }
}