0

我有以下代码作为游戏的一部分:

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.Black);

        spriteBatch.Begin();

        terrainSprite.Draw(spriteBatch);

        if (resourceMap.pixels.IsDisposed == false)
        {
            resources.Draw(spriteBatch, spriteFont);
        }

        spriteBatch.End();

        base.Draw(gameTime);

       //Disposes the texture here:
        resources.pixels.Dispose();
    }

    //In the resources class
    public void Update()
    {       
        //gD = graphics device
        pixels = new Texture2D(gD, 800, 353);

        //big update method
        //manipulate the pixels texture
    }

当我打开任务管理器并查看资源监视器时,“myGame.exe”的内存使用量不断增加约 8 KB(我意识到这很小,但我的游戏拥有大量数据,所以我节省了每一点can 很重要,而且它建立起来相当快)。这是在所有其他代码被注释掉之后,除了这里显示的内容。然后,当我注释掉代码:“pixels = new Texture2D(gD, 800, 353);”时,内存使用量保持不变。我也尝试了 GC.Collect(),但没有骰子。

我还能做些什么来阻止它吗?(对不起,摆脱代码不是一种选择:p,更新纹理比我遇到的任何其他使纹理变为空白的方法要快得多)

4

2 回答 2

2

取决于您的Game配置,实际上还有许多其他因素,例如一切运行速度有多慢等,Update并且Draw彼此之间并不完全同步,并且不能保证以以下方式运行:

Update
Draw
Update
Draw
Update
Draw
Update
Draw
....

因此,既然你Dispose在其中一个并在另一个中创建一个全新的,那么肯定会发生这样的事情:

Update: create new
Update: create new //PREVIOUS ONE LEAKED!
Draw: disposes only current
Update: create new
Update: create new //AGAIN LEAK
Draw: disposes only current
...

因此,不要Dispose以这种方式分开;Dispose无论如何,每个新创建一次。

我还应该补充一点,纹理以及其他一些 XNA 类(声音和音乐,以及Effects 等等)都是非托管资源,这意味着 GC 根本看不到它们。你必须调用Dispose这些。

正如 Andrew 在他的评论中指出的那样,避免这些陷阱的最佳方法是不要经常重新创建纹理 - 只需重复使用相同的纹理并根据需要对其进行修改。

于 2013-04-17T03:53:32.930 回答
0

垃圾收集器似乎没有完全处理 Texture2D。

因此,当您停止使用它时(在重用引用它的变量时,例如此处,或在 OnDestroy 回调期间),您必须手动销毁纹理。这里 :

if(pixels != null) {
  Destroy(pixels);
}
pixels = new Texture2D(gD, 800, 353);
于 2020-02-28T10:54:56.733 回答