提交到主`DispatchQueue`的项目是否会中断当前正在主线程上执行的代码?

问题描述 投票:0回答:1

下面的代码用于在后台线程上执行长时间运行的计算:

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重置为新对象之前执行。如果可以,则可以将过时的计算输出显示给用户。

swift multithreading
1个回答
0
投票

不,不可能。主队列是串行队列。如果代码在主队列上运行,则不能运行“其他”主队列代码。您的DispatchQueue.main.async有效表示:“等待直到在主队列上运行的所有代码自然结束,然后then在主队列上运行它。”

另一方面,DispatchQueue.global()不是串行队列。因此,从理论上讲,两个对calculateOutput的调用可能会重叠。那不是您想发生的事情;您想确定在执行任何calculateOutput实例之前(我们将继续处理latestKey),然后再启动另一个实例。换句话说,您要确保序列

  • 在主线程上设置latestKey
  • 在后台执行calculateOutput
  • 查看主线程上的latestKey

连贯发生。确保此方法的方式是预留使用DispatchQueue(label:)创建的DispatchQueue,您将始终使用它们运行calculateOutput。默认情况下,该队列将是串行队列。

© www.soinside.com 2019 - 2024. All rights reserved.