3

I'm developing C# application for windows phone 8.1 (Silverlight). Lately I've came across the problem connected to application falling asleep and storyboards.

The construction goes as follows:

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();
    }
}

There is a NullReferenceException thrown from inside of _storyboard.Begin() if application is placed in background between "Prepare" and "Go" (about 10% reproduction rate). Of course it ends up with crash.

I was not able to determine problem source and as I need quickfix for that I've decided to just catch this NullRefereneceException in this rare scenario. This is where real question starts. I've changed "Go" implementation to:

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

Afterwards the crash is not reproducible at all, but the problem is that "BreakPoint 2" is never hit (no printout in Output either). "BreakPoint 1" is normally hit and printed as well. Changing NullReferenceException to other Exception type (not parent type ofc) causes crash to reappear.

So... What's going on here? Is this crash cached or not? What kind of weird behavior is that? Is it safe to assume that it will work as expected?

Additional question: Maybe you know why the original code crashes in the first place?

EDIT: End of stack trace of internalException of TargetInvocationExceptions looks as follows:

   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()
6
  • 1
    So is the program still crashing or not? If you have it catch a generic Exception what happens? Commented Jul 28, 2015 at 9:31
  • It's not crashing, but it looks like code inside catch is not performed. Any exception type that is parent of NullRefrenceException is fixing crash. Any other exception type does not fix the crash.
    – Yester
    Commented Jul 28, 2015 at 9:33
  • 3
    If you're getting a TargetInvocationException, then that is what you need to catch. The InnerException property is likely your NullReferenceException, but you can't catch on that (except if you're using C# 6.0 where you can do: catch (TargetInvocationException ex) when (ex.InnerException is NullReferenceException) ). Commented Jul 28, 2015 at 11:13
  • 1
    How sure are you that Prepare is being called before Go? Commented Jul 28, 2015 at 11:17
  • About 100% sure. Both are called in only one context and one after another. Also I've checked for _storyboard beeing null inside Go(), if that what you are worry about.
    – Yester
    Commented Jul 28, 2015 at 11:18

1 Answer 1

4
+150

I know that you've said that you've tried to use parent types for NullReferenceException, but please try the following without running in the debugger:

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

My suspicion is that the catch is not firing because you are running from within the debugger. Also try System.Diagnostics.Debugger.Launch(); in the catch if .Break(); does not work. And finally also try throw; in the catch if .Launch(); does not work.

If the debugger attempts to launch in either case, then you have another clue.

UPDATE:

I can't give you all of the reasons why this might happen as it may not be possible to determine precisely what is causing it in your situation.

I've seen behavior like this due to use of multithreading. Multithreading can behave differently when running with a debugger attached then without. Timing issues and race conditions can prevent exceptions from being thrown while in the debugger that otherwise may occur frequently when there is no debugger attached.

I've also encountered instances where System.Diagnostics.Debugger.IsAttached was used in third party code and even my team's code which caused the application to behave differently based on if statements using this check.

And lastly, I've had times where I could not come up with a specific reason why the behavior was occurring. I've learned to use the System.Diagnostics.Debugger.Break() method whenever I see behavior exhibited differently depending on whether a debugger is attached or not. Sometimes it really is just a gut feeling.

3
  • You're right, the code inside this catch is performed even though debugger does not stops on breakpoints there. Debugger.Break() causes application to end without breaking debugger session. I've also tried to change some graphical elements from catch block and it works perfectly fine. Can you explain that behavior?
    – Yester
    Commented Jul 31, 2015 at 13:33
  • @Yester I've updated the answer with some additional information. Unfortunately, without having a copy of your precise setup and visual studio solution, I cannot give you an exact answer as to why this behavior is manifesting in your situation. I've provided a couple of things to look for in the updated answer. Unfortunately you may have to accept that you might not be able to determine why this is happening in your case. But keep the fact that this has happened in the back of your mind so that you can try to recognize it when it happens again in another situation. That's what I've done. Commented Jul 31, 2015 at 15:32
  • Thanks for help. It doesn't explain why all this happens, but it's probably best thing I can get now :-)
    – Yester
    Commented Aug 3, 2015 at 9:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.