【问题标题】:Closure argument passed as @noescape to Objective-C has escaped作为@noescape 传递给Objective-C 的闭包参数已经逃逸
【发布时间】:2020-10-20 23:02:47
【问题描述】:

我正在尝试使用资源包装器进行线程安全访问。在我的实现中,awaitedValue 字段通过串行队列执行资源的同步read。出于某种原因,每当我尝试读取此属性时,我的应用程序都会因错误而崩溃,这对于同步代码来说没有意义。

class ThreadsafeResource<T> {
    private let accessorsQueue: DispatchQueue
    private var resource: T
    
    //MARK: Initializers
    init(_ resource: T) {
        self.resource = resource
        self.accessorsQueue = DispatchQueue(label: "X")
    }

    //MARK: Synchronous access
    var awaitedValue: T {
        accessorsQueue.sync(flags: .inheritQoS) { // Point where my app crashes.
            self.resource
        }
    }
}

我尝试从mainglobal(.utility) 队列中读取它——结果相同。对资源的异步调用工作正常。

【问题讨论】:

    标签: ios swift grand-central-dispatch synchronous dispatch-queue


    【解决方案1】:

    当您提供flags 时,问题就显现出来了。如果删除它,问题就会消失。

    查看堆栈跟踪,它在 _syncHelper 中失败,它声明闭包在不是真的逃逸时,AFAICT。当您提供flags 并且它是not empty 时,会调用_syncHelper 的这种再现。

    我将提交一份错误报告,因为 _syncHelper 将该参数设置为 @escaping 似乎是不正确的。

    目前,我建议您直接删除 flags 参数或考虑使用不同的同步机制。

    【讨论】:

    • 我玩了一圈,发现除了.barrier 之外的任何标志都会导致此崩溃,因此基本上任何与QoS 相关的标志。至于解决方法:DispatchWorkItems 不会发生这种情况,带有标志,同步执行。
    • 对于那些跟随的人,这个错误报告似乎是bugs.swift.org/browse/SR-12479
    猜你喜欢
    • 2015-06-10
    • 2011-09-13
    • 1970-01-01
    • 2023-03-13
    • 2018-01-28
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多