none
metro抛出异常无法正常工作 RRS feed

  • 问题

  • 背景:我希望在一些我认为程序无法正常运行的情况下抛出异常,于是在 vs11 beta 生成的metro 风格的 directx 项目代码做了一个实验。

    具体过程:

    1.创建工程,编译,运行正常;

    2.参考文档Exceptions (Visual C++ for Windows Runtime) 修改 main 函数,原来的函数为

    [Platform::MTAThread]
    int main(Platform::Array<Platform::String^>^)
    {
        auto directXAppSource = ref new DirectXAppSource();
        CoreApplication::Run(directXAppSource);
        return 0;
    }

    修改成

    [Platform::MTAThread]
    int main(Platform::Array<Platform::String^>^)
    {
        try
        {
    	throw ref new Platform::COMException(1); // 抛出异常,暂时用 1 作为编号
    	auto directXAppSource = ref new DirectXAppSource();
    	CoreApplication::Run(directXAppSource);
        }
        catch (Platform::COMException^ e)
        {
        }
    
        return 0;
    }

    3.但是运行后会出现如下错误

    4.Output 窗口显示如下:

    /*一堆的 pdb 无法加载*/
    First-chance exception at 0x772756C4 in MarbleMaze.exe: Microsoft C++ exception: Platform::InvalidArgumentException ^ at memory location 0x00D6F7E4.
    The program '[5352] MarbleMaze.exe' has exited with code 0 (0x0).


    有没有什么想法?是我用错了吗?



    2012年3月21日 9:48

答案

  • Well, 也就是说是调用的方法本身抛出异常,而不是你throw的。 因为系统是不知道是否支持DX11的。 所以这个问题就是,这个异常并没有抛到你所在的try catch, 而是在你的 CreateDeviceResources 中的方法中就处理了,可以说得是可能你调用的方法本身并没有异常处理,所以导致运行时崩溃。 请重新思考的方法,确定需要通过异常来达到有好的提示目的?  因为通过异常本身就不是安全的方法,而且消耗大,难以控制。 

    你应该用下面的方式来判断所支持的DX特性: http://msdn.microsoft.com/en-us/library/ff476875(VS.85).aspx


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月22日 10:06
    版主
  • dx11一般不用担心硬件支持,兼容Dx9,能跑Win8就是支持了.移动平台我估计也不会用到DX11的那些高级硬件特性。
    应该只要不调用高版本shader就不会出错吧,反正D3D11CreateDevice时就能知道,不知道移动平台硬件要求支持到哪个Level

    Win8开发群 QQ群:95331609, (Metro DirectX11.1)



    2012年3月22日 10:24
  • 继续运行什么会出错? 不支持就不要Render,不就没问题了吗


    Win8开发群 QQ群:95331609, (Metro DirectX11.1)

    2012年3月22日 13:43

全部回复

  • 不是抛出了吗,你希望怎样呢


    Win8开发群 QQ群:95331609, (Metro DirectX11.1)

    2012年3月21日 10:30
  • 你在代码中 自己抛出了一个异常,代码当然无法继续执行了,肯定要报错了啊。

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月21日 17:15
    版主
  • 但是我有 catch 了啊,它不应该是接着运行 return 0 吗?

    2012年3月22日 5:46
  • App 都没有正常 run起来之前抛个异常,肯定会造成程序崩溃; 况且在VS调试中,一般会在抛出异常时暂停调试,定位到异常处。

    如果你真要实验是不是会catch 异常,你也要在一个 Page 中,或者建立一个简单的Console Application 来测试。 不过相信教科书上讲的,try 里面 抛出异常是会被catch的,只不过你的这个写法,即使catch了系统也会认为你的应用崩溃的,因为没有正常启动。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月22日 6:00
    版主
  • 就是这样,那个框框又不是异常,只是说没有正常激活程序


    Win8开发群 QQ群:95331609, (Metro DirectX11.1)

    2012年3月22日 6:10
  • 如果我把抛异常的位置往后挪一挪,在

    // These are the resources that depend on the device.
    void DirectXRender::CreateDeviceResources()
    {
        // 创建显卡设备时,如果发现不支持DirectX 11,在这里抛出异常,结果依然不是预期的
    }

    运行时有类似上面的“无法激活窗口程序”的错误,只是后面的信息被换成了:

    the target process aborted before activation completed.

    难道我不能通过这种方式做?

    2012年3月22日 8:34
  • 如果你调用的代码中有异常,通过try catch自然会被捕获,为什么你要手动throw一个出来。还有 CreateDeviceResources 你是在什么时候被调用?如何调用的?

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月22日 8:57
    版主
  • CreateDeviceResources() 是在 CCFrameworkView 被初始化的时候调用的。

    之所以要手动抛出异常,是因为系统并不知道显卡是否支持 dx11,继续执行下去会直接崩掉,我希望给用户一个更加友好的提示后停止程序的运行。

    2012年3月22日 9:23
  • Well, 也就是说是调用的方法本身抛出异常,而不是你throw的。 因为系统是不知道是否支持DX11的。 所以这个问题就是,这个异常并没有抛到你所在的try catch, 而是在你的 CreateDeviceResources 中的方法中就处理了,可以说得是可能你调用的方法本身并没有异常处理,所以导致运行时崩溃。 请重新思考的方法,确定需要通过异常来达到有好的提示目的?  因为通过异常本身就不是安全的方法,而且消耗大,难以控制。 

    你应该用下面的方式来判断所支持的DX特性: http://msdn.microsoft.com/en-us/library/ff476875(VS.85).aspx


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月22日 10:06
    版主
  • 是的,我的确是用你所给的方法来判断显卡是否支持 dx11,这些判断方法本身是不会抛出异常的

    但是它会告诉我,我显卡的 featrue level 过低,当这种情况出现的时候,我必须给用户提示,并终结自己

    所以我想到了当 featrue level 过低时,认为的抛出一个异常,并 catch 那个异常(提示用户),接着走到主程序的 return 0 终结自己

    不知道我这种思路是否正确?

    2012年3月22日 10:21
  • dx11一般不用担心硬件支持,兼容Dx9,能跑Win8就是支持了.移动平台我估计也不会用到DX11的那些高级硬件特性。
    应该只要不调用高版本shader就不会出错吧,反正D3D11CreateDevice时就能知道,不知道移动平台硬件要求支持到哪个Level

    Win8开发群 QQ群:95331609, (Metro DirectX11.1)



    2012年3月22日 10:24
  • 即使你需要提示给用户,也应该用 if 判断 而不是抛异常。

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月22日 10:27
    版主
  • dx11一般不用担心硬件支持,兼容Dx9,能跑Win8就是支持了.移动平台我估计也不会用到DX11的那些高级硬件特性。
    应该只要不调用高版本shader就不会出错吧,反正D3D11CreateDevice时就能知道,不知道移动平台硬件要求支持到哪个Level

    Win8开发群 QQ群:95331609, (Metro DirectX11.1)



    在我实验室的机器上出现过这种情况,一张集显,一张独显,集显不支持 directx11,但独显支持,在创建 d3ddevice 时如果选定的是集显,程序会崩溃掉(即使现在可以避免使用高阶函数,但也无法保证以后不用啊)

    既然这样,也就不排除就一张集显,且无法支持 directx 11 了,这个情况下想要给用户一个提示,否则用户只会认为这是我们程序的错。

    2012年3月22日 12:21
  • 即使你需要提示给用户,也应该用 if 判断 而不是抛异常。

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    假设我用 MessageDialog() 进行提示,但我发现它只有一个异步的接口,也就是说,显示对话框时后面的代码会被继续运行,程序就有可能立即崩溃了,用户还是无法看到那个提示。
    2012年3月22日 12:26
  • 继续运行什么会出错? 不支持就不要Render,不就没问题了吗


    Win8开发群 QQ群:95331609, (Metro DirectX11.1)

    2012年3月22日 13:43
  • 即使你需要提示给用户,也应该用 if 判断 而不是抛异常。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    假设我用 MessageDialog() 进行提示,但我发现它只有一个异步的接口,也就是说,显示对话框时后面的代码会被继续运行,程序就有可能立即崩溃了,用户还是无法看到那个提示。

    如果你需要MessageDialog来显示错误,你就应该通过在返回的TaskAction中去继续你的代码,等显示完成后再继续。   当然我们还是不能认可你的这种设计,应该是判断支持哪些特性,然后就只使用这些特性,而不是既然不支持还是使用,然后让他自己抛异常,我来捕获。 就像先犯错,再来纠正;和先预防不犯错一个道理。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月23日 3:11
    版主
  • 其实我是判断不支持,就抛出异常,并在一个统一的地方捕捉此异常,给提示,并停止程序
    2012年3月23日 3:48
  • 其实 Windows.UI.Xaml.Application class 提供了一个捕获所有未被处理的异常的方法: Application.UnhandledException event  你只需要实现这个事件,它就可以捕获所有应用中未被 handled 的异常。注意,前提是这个异常是unhandled的。  还有,如果你在VS调试的时候钩选了让VS在有未处理异常停止的选项,调试的时候可能进不去这个事件,所以你还需要 Debug menu > Exceptions > 去掉你不想让VS暂停的那些异常类型。

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月23日 5:25
    版主