Lock contention during load screen animations

If your game has a lot of content, your LoadContent call might take a while.

If loading takes a long time, you might want to display a "please wait" message.

If you value polish, you might even decide this message should be animated in some kind of awesomely cool way.

It is pretty easy to do that by firing up a background thread at the start of LoadContent, and having it do something like:

    while (!finishedLoading)

Here be dragons! The above code will work, but is liable to make your loading hundreds of times slower.

The reason is that every time you touch the graphics device from a different thread, the framework takes out a critical section, in order to avoid heisenbadness. If the animation is constantly redrawing, the animation thread will pretty much always own this lock, so any time your load function wants to create a graphics resource such as a texture, vertex buffer, or shader, it must wait until the animation thread releases it. This might take a while if the animation thread is just constantly looping over the same piece of draw code!

The solution is to slow down your animation thread by inserting a sleep call, which stops it hogging the graphics device.

The animated LoadingScreen class in our Network State Management sample shows one way to implement this.

Comments (3)

  1. kolorahl says:

    I’m currently creating a couple ‘background’ threads to run my loading code on and run the animation code while those loading threads are still alive; is that solution similar to the one described here? Will this help animated loading screens load content faster?

  2. Similar to the question above:

    I wonder if there is a reason that drawing can’t be done as normal, with loading done in a separate thread?

  3. ShawnHargreaves says:

    Whichever way around you put the two threads, the same issue occurs: you have one thread trying to draw stuff, at the same time as another thread tries to load stuff. Both operations require use of the graphics device, which takes out a lock, which serializes your code. If both threads are running flat-out, one can end up starving the other, so it can be useful to coordinate this kind of workload more carefully in order to make sure the two threads are not both just running flat-out.

Skip to main content