Swift多線程開發(fā) - 6. Operation 隊列

Operation支持以下三種添加任務的方式

  • Operation
  • 傳閉包
  • Operation數(shù)組

Operation管理

OperationQueue會根據(jù)QoS優(yōu)先級以及其它依賴來執(zhí)行狀態(tài)為isReadyOperation。每個Operation只能被執(zhí)行一次,所以如果一個Operation實例被添加到了一個隊列中,那么它就不可以再被添加到別的隊列中了。所以重復執(zhí)行的任務可以通過實例化多個Operation子類來達到目的。

等待完成

如果看OperationQueue的底層,你會發(fā)現(xiàn)一個方法叫waitUntilAllOperationsAreFinished。這個方法的調用會阻塞當前線程,所以不要在主線程調用。如果真的需要,就重新啟用一個串行隊列來調用它。

優(yōu)先級

OperationQueue就像DispatchGroup,任務會有不同的QoS優(yōu)先級。
默認的優(yōu)先級是.background,類似DispatchGroup,隊列的優(yōu)先級可能會因為任務的優(yōu)先級更高而被升級來匹配。

暫停

設置isSuspended屬性為true將會在暫停隊列后續(xù)任務的執(zhí)行。當前正在處理的任務還會繼續(xù),后續(xù)的任務知道isSuspendedfalse才會繼續(xù)執(zhí)行

最大Operation數(shù)

默認情況下,DispatchQueue的最大任務數(shù)和設備能支持的并發(fā)數(shù)一樣。
設置maxConcurrentOperationCount即可限制。當它為1的時候,這個隊列就相當于是一個串行隊列。

underlyingQueue

在還沒有添加operation之前,把一個已經存在的DispatchQueue隊列設置為underlyingQueue會使得OperationQueue里的所有任務QoS優(yōu)先級與DispatchQueue優(yōu)先級相同。這樣設置可以將一系列不同的優(yōu)先級的任務根據(jù)DispatchQueue來重新設定。

例子

下面的代碼在UITableView上展示經過濾鏡過濾的圖片,原圖片從本地讀取,濾鏡圖片則是實時渲染。
如果在主線程直接渲染會引起卡頓,這里通過OperationQueue實現(xiàn)異步渲染和加載

例子中建立的默認參數(shù)Operation隊列是串行的

class FilterTableViewController: UITableViewController {
  private let queue = OperationQueue()
  
  override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 10
  }
  
  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "example", for: indexPath) as! PhotoCell
    
    let image = UIImage(named: "\(indexPath.row).png")!
    
    let op = FilterOperation(image: image)
    op.completionBlock = { // Operation完成閉包
      DispatchQueue.main.async
        {
          guard let cell = tableView.cellForRow(at: indexPath) as? PhotoCell else {
            return
          }
          cell.update(image: op.outputImage)
      }
    }
    queue.addOperation(op) // 不需要主動調start(),加入隊列之后就會根據(jù)系統(tǒng)資源安排執(zhí)行
    
    return cell
  }
 }


final class FilterOperation: Operation {
  private static let context = CIContext()

  var outputImage: UIImage?

  private let inputImage: UIImage

  init(image: UIImage) {
    inputImage = image
    super.init()
  }

  override func main() {
    guard let filter = Filter(image: inputImage, radius: 3), // CIFilter封裝 
      let output = filter.outputImage else {
        print("Failed to generate tilt shift image")
        return
    }

    let fromRect = CGRect(origin: .zero, size: inputImage.size)
    guard let cgImage = TiltShiftOperation.context.createCGImage(output, from: fromRect) else {
      print("No image generated")
      return
    }

    outputImage = UIImage(cgImage: cgImage)
  }
}



作者博客地址

系列文章鏈接

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容