Few ContentManager questions

Hi,

I couldn’t find clear answers on the following:

1/ When I call Load(“someTexture”), does the ContentManager tracks if the texture was already loaded? Or does it just loads a new copy each time?

2/ Can I safely use the ContentManager from a background thread?

It keeps loaded content in a dictionary and first checks in there when loading. Additionally it will call Dispose on disposable assets when they are unloaded.

The dict is not used in a thread safe way, so be careful with that.

You can check out the source here: https://github.com/MonoGame/MonoGame/blob/develop/MonoGame.Framework/Content/ContentManager.cs
The dictionary is called loadedAssets and is defined at https://github.com/MonoGame/MonoGame/blob/develop/MonoGame.Framework/Content/ContentManager.cs#L28

Thank you Jjagg for your support :slight_smile:

I’m loading almost all the content from a new thread and it works very well. The content I load in LoadContent() is the content needed to show a “loading screen”.

protected override void LoadContent()
{
	// Load the rest of the assets
	var thread = new Thread(LoadGame);
	thread.SetApartmentState(ApartmentState.STA);
	thread.Start();
}

private void LoadGame()
{
	// Textures
	monoGameLogoSquareTexture = Content.Load<Texture2D>("monoGameLogos/SquareLogo_128px");
	enemyTexture = Content.Load<Texture2D>("enemy");
	inventoryTexture = Content.Load<Texture2D>("inventory");
	inventorySelectedItemTexture = Content.Load<Texture2D>("inventorySelectedItem");
	powerUpsBackgroundTexture = Content.Load<Texture2D>("chances/powerUpBackground");
}

I had to specify the thread.SetApartmentState(ApartmentState.STA) because I need to copy some text in the clipboard in some circumstances.

Isn’t the STA ApartmentState supposed to be assigned on the main thread only?
I’m surprised it is possible to assign multiple STA thread.

Anyway this pretty much answers my question, thanks =)

Check the links in this answer for an explanation about STA apartment state

STA Apartment State

Hope this help.

Robe.

You have few items to load, so it currently works because the thread is faster than the part asking for a loaded resource, but what happens if your LoadGame() method takes 10s or more ?
I think it is missing a synching mechanism.
Something like a Manual or AutoResetEvent at the end of LoadGame() to signal the main thread it has finished its job.

@Alkher, I don’t need a synching mechanism because I’m using a screen system and I change the screen to the main menu screen at the end of LoadGame(). I’ve simulated a long time (50 seconds) load with Thread.Sleep() in the LoadGame() method and it works as expected.

And I’ve much more resources to load, sounds, songs, spriteFonts, etc. I just shown here a small piece of code to show the idea.

I think that @raizam will probably need a synching mechanism.

Thank you for your suggestion.

You’ve guessed right, I’m currently working on it :slight_smile:

I’m using the .NET Task Parallel Library for asynchronous operations, it much easier to work with it.
I will probably share some code later on

1 Like

I think I have something sharable: https://gist.github.com/raizam/df2f62801ab989dbb55226d911dd917f

This makes threading in Monogame easier.
I’ve created a TaskManagerComponent, which is a regular GameComponent, this is used like this:

    //In your game class

    Color clearColor = Color.CornflowerBlue;
    protected override void Initialize()
    {

        TaskManagerComponent  taskManager = new TaskManagerComponent(this);
        Components.Add(taskManager);


        taskManager.ExecuteInBackground(() =>
        {
            Thread.Sleep(2000);

            //ThrowIfNotInGameThread(); //this throws here

            return Color.Aqua;
        }).Then(task =>
        {
           
              ThrowIfNotInGameThread();  //Here we are back in the game thread, inside Update()

            // 'task' is a Task Parallel Library result instance: Task<Color>
            clearColor = task.Result;

        });


        base.Initialize();


    }
1 Like

I’ve read somewhere that GameComponent and DrawableGameComponent should be avoided. Verify this if you have a chance.

This is very vague… If you like the way they work you can use them, there’s nothing inherently wrong with the component system.

So you throw an exception to sync between the task(s) and the game’s thread ?

He just put that there to show that the code runs in the main game thread. When the GameTasks internal task finishes it puts the ‘Then’ task in a queue in its TaskManagerComponent. When Update is called on the TaskManager (on base.Update in Game through the component stuff) it executes whatever is in that queue (on the same thread).

I don’t know where you’ve read that, but in fact… GameComponents are awesome :grinning:
It encourages separating logic in small units that each have its own role, and each of these behavior can be added or removed depending on the need, hence this helps reusability.
The concept of Separation of Concerns is the key of a good architecture.

As Jjagg points out, this is just to prove that the result of the background operation is passed back to the game loop: because no exception is thrown, it passes the test. This means we are safe with synching concerns. The only thing you can do wrong here is to use instances that belong to the game thread inside ExecuteInBackground, don’t do that =)

Sorry guys I think I didn’t read the whole post about avoid using the DrawableGameComponent. Here’s where I read it.

Thank you @Jjagg for your explanation.

I think I’ll use them :slight_smile:

Not sure how he got 20 votes, his points aren’t convincing, and his examples are futile. This contracdicts what’s currently happening in the software industry. The history of software architecture is quite young, the evolution could be pictured as: spaghetti -> lasagna -> ravioli

When I started my career, we were told that the lasagna architecture was the best, (N-Tier architecture)…
But in practice everyone realized the lasagna approach is not so efficient, too many layers and it was too much maintenance. Then the ravioli (Components) approach emerged, and this is AFAIK still the dominant paradigm today.

Unity is massively based on component, and it looks like it’s working well, they could build a big ecosystem, everyone is using components made by others, and everything is pluggable. I haven’t tried UE4, but I’m pretty sure it has a component-based architecture too.
So, what this guy say is not what’s happening in ‘the real world’ as he says.

@vcRobe in the stackexchange link you’ve provided, there is another answer contradicting the accepted one, which has more vote. Since you believe whoever has votes, maybe he can convince you :slight_smile:

There is an old thread from 2007 in the Ogre forums about components: http://www.ogre3d.org/forums/viewtopic.php?t=36015. This is pretty much when the Component pattern started to be a thing, that’s an interesting read.

I think you both already achieved a consent with his last post.
So as far as I can tell, everyone here shares the same opinion.
:slight_smile:

haha. that’s why I need to sleep sometimes :dizzy_face:
that’s nice =)