【问题标题】:How to properly catch Microsoft.Xna.Framework.Graphics.DeviceLostException?如何正确捕获 Microsoft.Xna.Framework.Graphics.DeviceLostException?
【发布时间】:2025-12-13 11:10:01
【问题描述】:

我使用 C# 和 XNA 开发了一个小游戏。我遇到了一个问题,当我锁定屏幕一段时间后,应用程序崩溃了:

Microsoft.Xna.Framework.Graphics.DeviceLostException

我假设异常是在 Draw() 例程中引发的,并试图通过以下方式捕获它:

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        try
        {
            // Draw game
            mySmallGame.Draw(gameTime);

            // TODO: Add your drawing code here
            base.Draw(gameTime);
        }
        catch (Microsoft.Xna.Framework.Graphics.DeviceLostException)
        {
            Console.WriteLine("Device lost.");
        }
    }

但是,该异常似乎没有被正确捕获。我稍后会处理它,到目前为止只有文本“设备丢失”。应该在游戏崩溃时打印出来。

堆栈跟踪是:

Microsoft.Xna.Framework.Graphics.dll!Microsoft.Xna.Framework.Graphics.GraphicsDevice.Present(tagRECT* pSource, tagRECT* pDest, HWND__* hOverride) + 0x1c6 bytes 
    Microsoft.Xna.Framework.Graphics.dll!Microsoft.Xna.Framework.Graphics.GraphicsDevice.Present() + 0x24 bytes 
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.GraphicsDeviceManager.Microsoft.Xna.Framework.IGraphicsDeviceManager.EndDraw() + 0x47 bytes    
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.EndDraw() + 0x2a bytes    
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.DrawFrame() + 0x13e bytes 
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.Tick() + 0x7a8 bytes  
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.HostIdle(object sender, System.EventArgs e) + 0x23 bytes  
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.GameHost.OnIdle() + 0x42 bytes 
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.WindowsGameHost.RunOneFrame() + 0x33 bytes 
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.WindowsGameHost.ApplicationIdle(object sender, System.EventArgs e) + 0x54 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(int grfidlef) + 0x3e bytes   
    System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID, int reason, int pvLoopData) + 0x3cd bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) + 0x155 bytes  
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x4a bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm) + 0x31 bytes  
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.WindowsGameHost.Run() + 0x9f bytes 
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.RunGame(bool useBlockingRun) + 0x150 bytes    
    Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.Run() + 0x23 bytes    
>   Project_Ares.exe!Project_Ares.Program.Main(string[] args) Line 14 + 0xb bytes   C#

【问题讨论】:

  • 发布堆栈跟踪。应该能够找出失败的地方。

标签: c# exception exception-handling xna draw


【解决方案1】:

获取堆栈跟踪。这应该告诉你它发生在哪里,以及它是否在你的代码中。 更新:查看堆栈跟踪,这都是您自己的代码外部的,并且充其量可以通过配置选项修复。我强烈建议您研究 MonoGame,如下所述

将异常处理放入您的 Main 方法中,因为到目前为止它更有可能捕获异常 - 始终首先依靠堆栈跟踪来告诉您在哪里引发了异常,这就是它的用途! (值得注意的例外:线程以及当异常被任务吃掉时)

尝试针对 MonoGame 而不是 XNA 重新编译您的游戏 - 后者已停产一段时间,而前者仍处于相对活跃的开发阶段,可能已经或可能尚未解决此问题。

【讨论】: