繁体   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