簡體   English   中英

Swift 等待異步任務

[英]Swift wait for async task

在后台線程中,我們有:

defer {
    cleanup()
}

loadData()

if error {
    return
}

processData()

DispatchQueue.main.asyncAfter(deadline: delay) {  //Delay = now + 0-2 seconds
     updateUI()
}

問題是我們要確保 defer cleanUp()代碼在updateUI()之后運行。 就目前而言,這不會發生,因為updateUI()異步運行。

我的想法是在延遲期間休眠/阻塞,而不是異步運行。 一旦updateUI()完成,這將使 defer cleanUp()運行。

你怎么能做到這一點? 或者,還有更好的方法?

您可以使用信號量告訴清理任務等待updateUI完成:

let semaphore = DispatchSemaphore(value: 1)
defer {
    semaphore.wait()
    cleanup()
}

loadData()

if error {
    // If we exit here, the semaphore would have never been used
    // and cleanup will run immediately
    return
}

processData()
semaphore.wait() // here, we claim the semaphore, making cleanup
                 // wait until updateUI is done
DispatchQueue.main.asyncAfter(deadline: delay) {
     updateUI()
     semaphore.signal()
}

意識到我可以改變代碼的結構:

loadData()

if error {
    log.error("Error")
} else {
   processData()
}

DispatchQueue.main.asyncAfter(deadline: delay) {  //Delay = now + 0-2 seconds
  updateUI()
  cleanup()
}

另一種選擇是使用DispatchGroup()

func doWork() {

   let group = DispatchGroup()

   group.enter() //Enter #1
   loadData { result in

      switch (result) {
      case .success(_):
           group.enter()//Enter #2
           processData { group.leave()//Leave #2 }
      case .failure(let error):
           //Do something nice with the error
           print(error)
      }

      group.leave()//Leave #1
    }

    //All the code inside this block will be executed on the mainThread when all tasks will be finished.
     group.notify(queue: .main) { [weak self] in

         guard let strongSelf = self else { return }

         strongSelf.updateUI()
         strongSelf.cleanup()
     }
}

private func updateUI() {
    //All your stuff
}

private func cleanup() {
    //All your stuff
}

private func loadData(completion: (Result<(), Error>) -> ()) {
    //All your stuff
    if error {
       completion(.failure(error))
    }
    else {
       completion(.success(()))
    }
}

private func processData(completion: () -> ()) {
    //All your stuff
    completion()
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM