swift 调度组会阻塞iOS中的主线程吗?

r8xiu3jd  于 2023-10-15  发布在  Swift
关注(0)|答案(1)|浏览(143)

我调用了一些代码来查询和更新CallKit调用扩展,偶尔我会看到挂起和调用超时。我想我应该把它放在主线程之外,这样它就不会阻塞UI,但事实并非如此吗?
UI堵塞了,我不知道是下面的代码,还是别的什么。
下面是查询函数:

private func queryCallExtensionStatusWithDispatchGroup() {
        let dg = DispatchGroup()
        dg.enter()
        self.doQueryCallExtensionStatusWithDispatchGroup(dispatchGroup: dg)
        Logger.trace(TAG + "queryCallExtensionStatusWithDispatchGroup() WAITING .... ")
        let dispatchTimeoutResult = dg.wait(timeout:  DispatchTime.now() + DispatchTimeInterval.seconds(30))
        if dispatchTimeoutResult == .timedOut {
            Logger.info(TAG + "queryCallExtensionStatusWithDispatchGroup() TIMED OUT")
        } else {
            Logger.trace(TAG + "queryCallExtensionStatusWithDispatchGroup() LEFT")
        }
    }

private func doQueryCallExtensionStatusWithDispatchGroup(dispatchGroup:DispatchGroup)  {
<snip>
    dispatchGroup.leave() 
}

他的召唤:

private let callExtensionQueue = DispatchQueue(label: "com.appname.serialQueue")

...
callExtensionQueue.async {
    self!.queryCallExtensionStatusWithDispatchGroup()
}
y0u0uwnf

y0u0uwnf1#

您的代码片段将阻塞callExtensionQueue使用的辅助线程,而不是主线程。
所以,除非你有一些sync调度到其他地方的callExtensionQueue(或者一些不寻常的线程爆炸场景),否则上面的代码不会阻塞主线程。
你的问题可能在其他地方。
如果你想确保你不会意外地从主队列调用一个函数,你可以添加一个dispatchPrecondition,这样如果你意外地从主队列调用这个函数,你会在调试版本中得到一个警告:

private func queryCallExtensionStatusWithDispatchGroup() {
    dispatchPrecondition(condition: .notOnQueue(.main))

    let group = DispatchGroup()
    group.enter()
    doQueryCallExtensionStatus {
        group.leave()
    }
    logger.trace("\(#function) WAITING .... ")
    let result = group.wait(timeout: .now() + .seconds(30))
    if result == .timedOut {
        logger.info("\(#function) TIMED OUT")
    } else {
        logger.trace("\(#function) LEFT")
    }
}

顺便说一句,在上面的例子中,标准的技术是一个完成处理程序闭包参数(如果你愿意,你可以把它设置为可选的),而不是把调度组传递给被调用的函数(不必要地纠缠这两个函数):

private func doQueryCallExtensionStatus(completion: (() -> Void)? = nil) {
    …
    completion?()
}

这样,所有与DispatchGroup相关的代码都被隔离到一个函数queryCallExtensionStatusWithDispatchGroup中。

相关问题