Why is it "risky" to dispatch work asynchronously on the main thread in SpriteKit?

102 Views Asked by At

In Use SpriteKit Objects within Scene Delegate Callbacks, this is mentioned:

Even dispatching work on the main thread asynchronously or at a later time is risky because the closure is likely to be done outside of the timeframe SpriteKit expects.

I wanted to know, why is this a problem? Isn't doing stuff on the main thread considered okay? And what do they mean by "outside the timeframe SpriteKit expects"? I would love an example that illustrates why dispatching work on the main thread asynchronously is "risky" in SpriteKit.

Edit: Right after that sentence, the document goes on to say

If you're experiencing a segmentation fault or other type of crash occurring deep within the SpriteKit framework, there's a good chance your code is modifying a SpriteKit object outside of the scene delegate callbacks.

I'm assuming they mean dispatching work to the main thread asynchronously, in some situations, might cause a crash (hence why they call it "risky"). So if someone can perhaps think of a situation where this might happen please let me know.

Some research I did

I have spent the last couple of days reading about RunLoops and even though it was super complicated for me I think I may have found a culprit for why it's "risky" to do this. There is a part in CFRunLoop.c that basically translates to:

let livePort = msgThatWeAreHandling.localPort
let dispatchPort = !mainQueueIsEmpty && isMainThread && runloop.isMain && runLoopMode.isCommon ? mainQueuePort : nil

if livePort == runLoopMode.timerPort {
    processTimers(currentRunLoop, runLoopMode, currentTime)
} else if livePort == dispatchPort {  
    // (2)
    drainDispatchQueue()
} else {  
    // (1)
    let inputSource = livePort.inputSource
    handleInputSource(inputSource)
}

When I was debugging with Xcode I saw this in the backtrace for the update(_:) function: __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__. This means the code labeled (1) is calling the update(_:) function. However, code sent to the main queue is executed at (2). Since these are different branches of the same if-statement I can see potential for things being done "outside of the timeframe SpriteKit expects". Could some issues regarding this part of the runloop be the culprit for why we can't send code to the main queue asynchronously? Please let me know what you guys think because I barely managed to understand the code in that file. Would love some input.

More Info

In the comment section of this post there is a comment that explains why dispatching work on the main thread asynchronously is risky. Here is the comment:

You might run into a situation where your async call is never done because the main thread is on some kind of infinite loop. You could also end up in a situation where the main thread is looking for the async call to finish, while at the same time your async call is waiting for the main thread to finish, locking your process up.

However, I feel these are risks associated with dispatching work to the queues in general rather than with respect to SpriteKit. Neither do these two situations, in my opinion, illustrate how things are being done "outside the timeframe SpriteKit expects". I wouldn't even know how it would be possible for the async call to wait for the main thread since it itself would be executing on it. As I am a beginner with queues, threads, game dev, etc., maybe someone can explain that part to me too.

0

There are 0 best solutions below