Catch不执行其代码

时间:2015-07-28 09:29:29

标签: c# silverlight windows-phone-8.1

我正在为Windows Phone 8.1(Silverlight)开发C#应用程序。最近我遇到了与应用程序入睡和故事板相关的问题。

构造如下:

class X : DependencyObject
{
    public static readonly DependencyProperty vProperty =
        DependencyProperty.Register("v", typeof(double), typeof(X), new PropertyMetadata(0.0));

    public double v
    {
        get
        {
            return (double)GetValue(vProperty);
        }
        set
        {
            SetValue(vProperty, value);
        }
    }

    private Storyboard _storyboard;
    void Prepare()
    {
        _storyboard = new Storyboard();
        var animation= new DoubleAnimation
        {
            From = 0,
            To = 1,
            BeginTime = 0,
            Duration = 0,
        };
        _storyboard.Children.Add(animation);
        Storyboard.SetTarget(animation, this);
        Storyboard.SetTargetProperty(animation, vProperty);
    }

    void Go()
    {
       _storyboard.Begin();
    }
}

如果应用程序放在“Prepare”和“Go”之间的背景中(大约10%的再现率),则会从_storyboard.Begin()内部抛出NullReferenceException。当然最终会崩溃。

我无法确定问题来源,因为我需要quickfix,因此我决定在这种罕见的情况下捕获这个NullRefereneceException。这是真正的问题开始的地方。我已将“Go”实现更改为:

    public void Go()
    {
        Debug.WriteLine("BreakPoint 1");
        try
        {
            _storyboard.Begin();
        }
        catch (NullReferenceException)
        {
            Debug.WriteLine("BreakPoint 2");
        }
    }

之后崩溃完全无法再现,但问题是“BreakPoint 2”永远不会被击中(输出中也没有打印输出)。 “BreakPoint 1”通常也会被点击和打印。将NullReferenceException更改为其他异常类型(不是父类型ofc)会导致重新出现崩溃。

所以...这里发生了什么?这个崩溃是否被缓存?这有什么奇怪的行为?假设它能按预期工作是否安全?

其他问题:也许您知道为什么原始代码首先崩溃了?

编辑: TargetInvocationExceptions的internalException堆栈跟踪如下所示:

   at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
   at MS.Internal.XcpImports.Storyboard_Begin(Storyboard storyboard)
   at System.Windows.Media.Animation.Storyboard.Begin()
   at X.Go()

1 个答案:

答案 0 :(得分:4)

我知道您已经说过您尝试使用父类型进行NullReferenceException,但请尝试在调试器中运行以下

public void Go()
{
    Debug.WriteLine("BreakPoint 1");
    try
    {
        _storyboard.Begin();
    }
    catch (Exception)
    {
        Debug.WriteLine("BreakPoint 2");
        System.Diagnostics.Debugger.Break();
    }
}

我怀疑是因为你是在调试器中运行而没有触发。如果System.Diagnostics.Debugger.Launch();不起作用,也请在catch中尝试.Break();。如果throw;不起作用,最后还要在catch中尝试.Launch();

如果调试器试图在任何一种情况下启动,那么你还有另一条线索。

<强>更新

我无法告诉您可能发生这种情况的所有原因,因为可能无法准确确定在您的情况下造成这种情况的原因。

由于使用了多线程,我看到过这样的行为。在没有附加调试器的情况下运行时,多线程的行为会有所不同。时序问题和竞争条件可以防止在调试器中抛出异常,否则在没有连接调试器时可能会频繁发生异常。

我还遇到过在第三方代码中使用System.Diagnostics.Debugger.IsAttached甚至我的团队代码的情况,这些代码导致应用程序基于使用此检查的if语句而表现不同。

最后,我有时无法想出行为发生的具体原因。每当我看到根据是否附加调试器而表现出不同的行为时,我就学会了使用System.Diagnostics.Debugger.Break()方法。有时它真的只是一种直觉