带有信号量用例的重大调度

iOS,swift,GCD,信号量

我今天遇到了一个问题,很想分享一下,以防有人遇到。

故事

我正在快速构建一个API,该API通过称为SendRequest的方法在内部向后端发送GETPOST请求。 此方法还可以交互并从数据库中获取数据(核心数据)。

SendREquest方法内部,有一个GetLatestUpdateTime调用,该调用将GET请求发送到服务器并检索Date( LatestTime ),然后我从该Date( latestTime )之后的数据库中获取所有记录,然后将这些记录上传到POST中的服务器上。使用Alamofire提出要求。

问题

在非常特殊的情况下,可能在同一时刻多次调用SendRequest方法。 GetLatestUpdateTime将返回相同的lastTime对象,然后从数据库中获取相同的dbObject ,最后将这些相同的dbObjects上传到服务器。 重复 !!!

可怕的重复将发生,而这不应该发生。

在上一个调用完成之前,必须存在防止再次调用SendRequest方法的方法。 因此,调用是同步的,当然不会阻塞主线程。

GCD

与我一起工作的方法是将Dispatch Queues与Semaphore一起使用

  1. 首先,我创建了一个调度队列
  var reportQueue = dispatch_queue_create(“ com.myapp.report”, 
  DISPATCH_QUEUE_SERIAL); 

2.和信号灯

 让信号量:dispatch_semaphore_t = dispatch_semaphore_create(0); 

零是这里的初始计数器,在我的情况下,我每次只想一次访问。

3.将sendRequest方法添加到队列

  dispatch_async(self.reportQueue){ 
  self.sendReport() 
  } 

4.在sendRequest方法中

并在调用GetLatestUpdateTime API之后,添加信号量等待

  dispatch_semaphore_wait(信号灯,DISPATCH_TIME_FOREVER); 

这将使初始计数器减少为-1 ,下一次对该部分“ sendRequest”的调用将不得不等待

5. 完成请求后,我们会发出信号量

  dispatch_semaphore_signal(self.semaphore); 

这将使计数器再次增加为0 ,从而允许再次输入关键部分。

这就是sendRequest方法的样子

 公共功能exitRegion(){ 
  dispatch_async(self.reportQueue){ 
  self.sendReport() 
  } 
  } 
 私人功能sendReport(){ 
  httpClient.getLatestUpdatedDate(String(self.userId)){(latestDateTime,错误)在 
 如果让_ =错误{ 
  debugPrint(“ \(#file),\(错误?.localizedDescription)”) 
///如果请求失败
  dispatch_semaphore_signal(self.semaphore); 
返回
  } 
 让地区报告:[ANARegion]?  = self.analyticsDBManaer.findRegionsReportsAfterDate(latestDateTime) 
 让regionjson = regionReports?.map({$ 0.dictionary}) 
  self.httpClient.postReport(regionsjson,完成:{(成功)在 
 如果成功{ 
  self.analyticsDBManaer.clearDataBase() 
  ///请求完成后,我们发出信号量 
  dispatch_semaphore_signal(self.semaphore); 
  } 
  }) 
  } 
  dispatch_semaphore_wait(信号灯,DISPATCH_TIME_FOREVER); 
  } 
  • DISPATCH_TIME_FOREVER:-可以更改,因此,如果出现问题,我们不会永远阻塞线程,也无法发出信号,例如
  let timeToWait = dispatch_time(DISPATCH_TIME_NOW,Int64(30 * NSEC_PER_SEC)) 
  dispatch_semaphore_wait(semaphore,timeToWait); 

正如我在谈论我的经验。 在调试时, timeToWait最好更高。

这是外观的可视化。

免责声明

理论解释和数字:p可能不是100%正确的,如果您进行了编辑,请发表评论。 谢谢。

感谢阅读,编码愉快。