2015-09-18 91 views
4

我有以下代碼:Console.WriteLine如何影響異常堆棧

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("Started"); 
     var res = GetSlowStringAsync(); 

     res.ContinueWith(
      c => 
       { 
        Console.WriteLine("Will it crash?"); 
        //Console.WriteLine(c.Result); 
       } 
      ); 

     //Console.WriteLine("Press any key"); 
     Console.ReadKey(); 
     Console.WriteLine("Continue on the main thread"); 

     GC.Collect(); 
     Console.WriteLine("Memory cleared"); 

     Thread.Sleep(10000); 
    } 

    public static async Task<string> GetSlowStringAsync() 
    { 
     await Task.Delay(2000); 
     throw new Exception("will you handle it?"); 
     return "somestring"; 
    } 
} 

也App.config中我加了以下幾行:

<runtime> 
    <ThrowUnobservedTaskExceptions enabled ="true" /> 
</runtime> 

我使用的Visual Studio 2015年14.0.23107.0 D14REL Target .Net Framework 4.6。 在「無調試開始」模式下執行。

如果之後的問題「它會崩潰」按任何按鈕,然後程序將崩潰。

但如果以取消

Console.WriteLine("Press any key"); 

,並在執行模式,那麼程序將不會崩潰「沒有調試運行」。爲什麼Console.WriteLine會影響引發異常的方式?

+0

適合我工作。 – Abhishek

+0

你的意思是這兩種情況都會在「無需調試開始」模式下產生異常? –

+0

它不扔在這兩個 – Abhishek

回答

3

我非常懷疑任何人都可以從您的代碼片段中重新生成問題。我的水晶球說你最後改變了程序,在最後添加了Thread.Sleep()。並隱藏了原始程序所具有的線程錯誤。假設通話不在那裏,我會寫這個答案。

  • 你不附帶
  • 的GC調試器中運行,可以運行該程序的程序
  • 的發佈版本:

    所有這些條件是真實的異常僅拋出。 Collect()調用實際上是垃圾回收 - 收集res對象。如果不滿足前兩個條件,則情況不會如此

  • 在GC.Collect()在main()方法結束之前結束之後,終結器線程有足夠的時間完成其工作。 Console.WriteLine()調用可以給它足夠的時間來運行TaskExceptionHolder終結器。不是一個保證,線程錯誤的問題。

改變結果的方法是工具>選項>調試>常規>取消「抑制JIT優化」選項。通過附加調試器可以確保結果不受影響。並且在GC.Collect()調用之前添加res = null;或將代碼移動到另一個方法中,以確保即使在Debug版本中也可以收集res。爲什麼GC.Collect()的行爲如此不可預測,詳見this post

你需要知道的另一件事情是,當程序忙於關閉時,異常被抑制。請注意使用TaskExceptionHolder finalizer中的Environment.HasShutdownStarted和AppDomain.CurrentDomain.IsFinalizingForUnload屬性。因此,如果終結器線程在執行它的工作時有點慢,那麼在終結器運行時關閉可能已經開始,並且您將不會得到異常。在GC.Collect()調用之後添加到Main()中的任何內容(如Console.WriteLine())可以提高看到異常的機率。

添加GC.WaitForPendingFinalizers()解決了線程錯誤並使結果可預測。那麼,更可預測:)

+0

我在VS2012也轉載了問題。今天@Abhishek也轉載了它。所以有人轉載了它。也許我們可以雙重檢查聊天? –

+0

我沒有安裝它了。無論如何,追逐線程缺陷是一項毫無結果的努力,它們在一臺機器和另一臺機器上的表現都不會很好。只需修復該錯誤。 –