2015-07-28 114 views
3

我正在爲Windows Phone 8.1(Silverlight)開發C#應用程序。最近我遇到了與應用程序入睡和故事板有關的問題。Catch不執行其代碼

構造變爲如下:

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

有從_storyboard.Begin()的內部拋出一個NullReferenceException如果應用設備被置於背景「準備」和「去」(約10%的再現速率之間)。當然,它最終會崩潰。

我無法確定問題的來源,因爲我需要quickfix,因此我決定在這種罕見的情況下發現這個NullRefereneceException。這是真正的問題開始的地方。我已經改變了「去」實施:

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

之後崩潰是不可複製的所有,但問題是,「斷點2」從不打(在輸出中沒有打印其一)。 「BreakPoint 1」通常也會被打印和打印。將NullReferenceException更改爲其他異常類型(不是父類型的c)會導致崩潰重新出現。

那麼......這裏發生了什麼事?這崩潰緩存或不?這是什麼奇怪的行爲?假設它能按預期工作是否安全?

附加問題:也許你知道爲什麼原始代碼崩潰的第一個地方?

編輯: 結束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

那麼程序仍然崩潰或沒有?如果你有它捕獲一個通用的'例外'會發生什麼? – user1666620

+0

它沒有崩潰,但它看起來像捕獲內的代碼不會執行。任何NullRefrenceException父類的異常類型都會修復崩潰。任何其他異常類型都不能修復崩潰。 – Yester

+3

如果你得到一個'TargetInvocationException',那麼這就是你需要捕獲的。 'InnerException'屬性可能是你的'NullReferenceException',但你不能理解(除非你使用C#6.0,你可以這樣做:'catch(TargetInvocationException ex)when(ex.InnerException是NullReferenceException)') 。 –

回答

4

我知道你說你已經嘗試使用父類型的NullReferenceException,但請嘗試以下沒有運行在調試器:

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

我懷疑是美中不足的是不觸發,因爲你是在調試器中運行。如果.Break();不起作用,請嘗試System.Diagnostics.Debugger.Launch();。如果.Launch();不起作用,最後還要在catch中嘗試throw;

如果調試器試圖在任何一種情況下啓動,那麼你有另一個線索。

UPDATE

我不能給你全部的原因,這可能發生,因爲它可能無法準確確定是什麼原因造成它在你的情況。

由於使用多線程,我見過這樣的行爲。使用不帶附加的調試器運行時,多線程的行爲可能會有所不同。定時問題和競態條件可以防止在調試器中拋出異常,否則可能在沒有附加調試器的情況下頻繁發生異常。

我也遇到過在第三方代碼中使用System.Diagnostics.Debugger.IsAttached的情況,甚至導致應用程序使用此檢查的if語句的行爲有所不同。

最後,我有時無法想出行爲發生的具體原因。我已經學會了使用System.Diagnostics.Debugger.Break()方法,只要我看到行爲的展現方式取決於調試器是否連接。有時它真的只是一個直覺

+0

你是對的,即使調試器沒有在那裏的斷點處停止,該catch中的代碼也會被執行。 Debugger.Break()使應用程序結束而不會打破調試器會話。我也嘗試從catch塊中改變一些圖形元素,並且它工作得很好。你能解釋這種行爲嗎? – Yester

+0

@Yester我已經用一些附加信息更新了答案。不幸的是,如果沒有您的精確設置和視頻工作室解決方案的副本,我無法給您一個確切的答案,說明爲什麼這種行爲在您的情況下顯現。我已經提供了一些在更新後的答案中查找的內容。不幸的是,您可能需要*接受*,否則您可能無法確定爲什麼會發生這種情況。但請保持這種情況發生在你的腦海裏,以便在另一種情況下再次發生時可以嘗試識別它。這就是我所做的。 –

+0

感謝您的幫助。這並不能解釋爲什麼會發生這種情況,但現在我可以得到最好的結果:-) – Yester