簡體   English   中英

提交到主“DispatchQueue”的項目是否會中斷當前在主線程上執行的代碼?

[英]Will an item submitted to the main `DispatchQueue` ever interrupt currently executing code on the main thread?

以下代碼用於在后台線程上執行長時間運行的計算:

enum CalculationInterface {

    private static var latestKey: AnyObject?   // Used to cancel previous calculations when a new one is initiated.

    static func output(from input: Input, return: @escaping (Output?) -> ()) {
        self.latestKey = EmptyObject()
        let key = self.latestKey!   // Made to enable capturing `self.latestKey's` value.  

        DispatchQueue.global().async {
            do {
                let output = try calculateOutput(from: input, shouldContinue: { key === self.latestKey })   // Function cancels by throwing an error.
                DispatchQueue.main.async { if (key === self.latestKey) { `return`(output) } }
            } catch {}
        }
    }
} 

這個函數是從主線程調用的,如下所示:

/// Initiates calculation of the output and sets it to the result when finished.
private func recalculateOutput() {
    self.output = .calculating    // Triggers calculation in-progress animation for user.
    CalculationInterface.output(from: input) { self.output = $0 }   // Ends animation once set and displays calculated output to user.
}

我想知道是否有可能在主線程運行我的代碼時執行推送到DispatchQueue.main的閉包。 或者換句話說,在self.output = .calculating但在self.latestKey重新設置為新對象之前執行。 如果可以,則可以向用戶顯示陳舊的計算輸出。

我想知道是否有可能在主線程運行我的代碼時執行推送到DispatchQueue.main的閉包

不,這是不可能的。 主隊列是串行隊列。 如果代碼在主隊列上運行,則不能運行“其他”主隊列代碼。 您的DispatchQueue.main.async實際上意味着:“等到在主隊列上運行的所有代碼自然結束,然后在主隊列上運行它。”

另一方面, DispatchQueue.global()不是串行隊列。 因此,理論上有可能對calculateOutput兩個調用重疊。 這不是你想要發生的事情; 您希望確保任何正在執行的calculateOutput實例在另一個實例可以啟動之前完成(並且我們繼續處理latestKey )。 換句話說,您要確保序列

  • 在主線程上設置latestKey
  • 在后台執行calculateOutput
  • 查看主線程上的latestKey

連貫地發生。 確保這一點的方法是將您使用DispatchQueue(label:)創建的DispatchQueue(label:)放在一邊,您將始終使用它來運行calculateOutput 默認情況下,該隊列將是串行隊列。

暫無
暫無

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

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