24

我有一個C#控制檯應用程序項目使用.NET 4.0,與Microsoft.Bcl.Async軟件包安裝。我用這個代碼:等待與.NET 4.0:有意義的堆棧跟蹤

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     Foo().Wait(); 
    } 

    static void Log(Exception ex) 
    { 

    } 

    private static async Task Foo() 
    { 
     try 
     { 
      await DoSomething(); 
     } 
     catch (Exception ex) 
     { 
      Log(ex); 
     } 
    } 

    private static async Task DoSomething() 
    { 
     throw new DivideByZeroException(); 
    } 
} 

如果我把一個斷點Log方法裏面,我讓我的DivideByZero異常,但堆棧跟蹤我看到的是:

at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task) 
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) 
at Microsoft.Runtime.CompilerServices.TaskAwaiter.GetResult() 
at AsyncStacks.Program.<Foo>d__0.MoveNext() in p:\Sandbox\AsyncStacks\AsyncStacks\Program.cs:line 25 

此堆棧跟蹤毗鄰因爲它不會告訴我異常實際拋出的位置。使用await

at AsyncStacks.Program.<DoSomething>d__3.MoveNext() in p:\Sandbox\AsyncStacks\AsyncStacks\Program.cs:line 35 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at AsyncStacks.Program.<Foo>d__0.MoveNext() in p:\Sandbox\AsyncStacks\AsyncStacks\Program.cs:line 25 

我怎樣才能從.NET 4.0的項目一個有用的堆棧跟蹤:

如果我改變我的項目面向.NET 4.5,我得到一個更有用的異常?

更新

「舊」 AsyncTargetingPack並拋出一個更好的堆棧跟蹤。這個問題似乎已經在「新」Microsoft.Bcl.Async引入。

+0

可能重複的[是否有可能獲得一個很好的堆棧跟蹤.NET異步方法?](http://stackoverflow.com/questions/15410661/is-it-possible-to-get-a-good -stack-trace-with-net-async-methods) – mnemonic

回答

7

更改Foo這似乎得到一個更好的結果:

private static async Task Foo() 
{ 
    await DoSomething().ContinueWith(t => Log(t.Exception), TaskContinuationOptions.OnlyOnFaulted); 
} 

更新:不過,壞處是你必須使用你每次使用await關鍵字相同時間.ContinueWith。也就是說,如果你等待一些也在等待的事情,你也需要.ContinueWith

+2

+1對於問題和答案 - 但是,我認爲你的意思是'Log(t.Exception.InnerException)' – YK1