[LibGDX] Changing Scene2D from a different Thread

Hey guys!

This is a threading issue more than a LibGDX issue, hence the subforum.

[quote=“docs of Scene2D”]The Stage and its constituents (like Actors and Listeners) are not thread-safe and should only be updated and queried from a single thread (presumably the main render thread). Methods should be reentrant, so you can update Actors and Stages from within callbacks and handlers.
[/quote]
I don’t understand how this is implemented. I’ve found out that changing the Actors from different threads are not a solution, and doing that has caused me grief for the last couple of hours.

Now, the question is as follows: How can I generate data on thread A, and then change an Actor on thread B to display that data.

Specifically, this is what I am looking to do: I have a GUI (Stage) that includes a highscore table (an Actor in this case). Whenever the highscore table is shown, I want to query my server for the latest global highscores. Upon completion, I want the highscore table (Actor) to be updated to show the highscores from the server.
Since the server communication is blocking, this needs to happen on a different thread. However, when it’s complete it’s important that the highscore table (Actor) is updated from the main thread.

How can I achieve this?

I have now made a thread-safe “HighscoreReading”-class that is accessed from the thread doing the networking. It also has a dirty-flag, for when it’s updated.

The HighscoreReading is also accessed by the Screen (main thread) every single frame to check if it is done (the dirty flag). If it is done, the data is added to the highscore-table (Actor). This works, because communication between the threads is going on through HighscoreReading which is thread safe. Right?

I feel like this is such a hack, though. There must be a better way to handle this. I really don’t want to poll HighscoreReading every frame via a synchronized method “isDirty()”.

Is there a way I can push to the model (Actor) when the HighscoreReading is done being changed by the networking thread (when the thread ends)?

Use Gdx.app.postRunnable so you only manipulate scene2d from the game thread.

That’s awesome! Thanks!