如何在不阻塞主线程的情况下添加SCNNodes? [英] How to add SCNNodes without blocking main thread?

查看:102
本文介绍了如何在不阻塞主线程的情况下添加SCNNodes?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建大量SCNNode并将其添加到SceneKit场景,这会导致应用冻结一到两秒钟.

I'm creating and adding a large number of SCNNodes to a SceneKit scene, which causes the app to freeze for a second or two.

我想我可以通过使用DispatchQueue.global(qos: .background).async()将所有动作放在后台线程中来解决此问题,但不要掷骰子.它的行为完全相同.

I thought I could fix this by putting all the action in a background thread using DispatchQueue.global(qos: .background).async(), but no dice. It behaves exactly the same.

我看到了此答案,并通过

I saw this answer and put the nodes through SCNView.prepare() before adding them, hoping it would slow down the background thread and prevent blocking. It didn't.

这是一个重现问题的测试功能:

Here's a test function that reproduces the problem:

func spawnNodesInBackground() {
    // put all the action in a background thread
    DispatchQueue.global(qos: .background).async {
        var nodes = [SCNNode]()
        for i in 0...5000 {
            // create a simple SCNNode
            let node = SCNNode()
            node.position = SCNVector3(i, i, i)
            let geometry = SCNSphere(radius: 1)
            geometry.firstMaterial?.diffuse.contents = UIColor.white.cgColor
            node.geometry = geometry
            nodes.append(node)
        }
        // run the nodes through prepare()
        self.mySCNView.prepare(nodes, completionHandler: { (Bool) in
            // nodes are prepared, add them to scene
            for node in nodes {
                self.myRootNode.addChildNode(node)
            }
        })
    }
}

当我调用spawnNodesInBackground()时,我希望场景能够继续正常渲染(也许以降低的帧速率),而新节点的添加速度则应以CPU可以接受的任何速度进行.相反,该应用程序完全冻结了一两秒钟,然后所有新节点立即出现.

When I call spawnNodesInBackground() I expect the scene to continue rendering normally (perhaps at a reduced frame rate) while new nodes are added at whatever pace the CPU is comfortable with. Instead the app freezes completely for a second or two, then all the new nodes appear at once.

为什么会这样,如何在不阻塞主线程的情况下添加大量节点?

Why is this happening, and how can I add a large number of nodes without blocking the main thread?

推荐答案

我认为使用DispatchQueue不能解决此问题.如果我替代其他任务而不是创建SCNNode,那么它可以按预期工作,因此我认为问题与SceneKit有关.

I don't think this problem is solvable using the DispatchQueue. If I substitute some other task instead of creating SCNNodes it works as expected, so I think the problem is related to SceneKit.

此问题的答案表明SceneKit具有它自己的私有后台线程,将所有更改批处理到该线程.因此,无论我使用什么线程创建SCNNodes,它们都最终与渲染循环位于同一线程的同一队列中.

The answers to this question suggest that SceneKit has its own private background thread that it batches all changes to. So regardless of what thread I use to create my SCNNodes, they all end up in the same queue in the same thread as the render loop.

我正在使用的丑陋解决方法是一次在SceneKit的委托renderer(_:updateAtTime:)方法中一次添加几个节点,直到它们全部完成为止.

The ugly workaround I'm using is to add the nodes a few at a time in SceneKit's delegated renderer(_:updateAtTime:) method until they're all done.

这篇关于如何在不阻塞主线程的情况下添加SCNNodes?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆