2011-06-16 109 views
8

這個例子 「失敗」:的try-catch異步異常

static async void Main(string[] args) 
{ 
    try 
    { 
     await TaskEx.Run(() => { throw new Exception("failure"); }); 
    } 
    catch (Exception) 
    { 
     throw new Exception("success"); 
    } 
} 

也就是說,與文本 「失敗」 異常堆滿了。

然後我嘗試以下解決方法:

static async void Main(string[] args) 
{ 
    try 
    { 
     await SafeRun(() => { throw new Exception("failure"); }); 
    } 
    catch (Exception) 
    { 
     throw new Exception("success"); 
    } 
} 

static async Task SafeRun(Action action) 
{ 
    var ex = default(Exception); 
    await TaskEx.Run(() => 
    { 
     try 
     { 
      action(); 
     } 
     catch (Exception _) 
     { 
      ex = _; 
     } 
    }); 
    if (ex != default(Exception)) 
     throw ex; 
} 

這並沒有幫助。

我想我的異步CTP刷新安裝可能會被解決。

這段代碼應該如我所期望的那樣工作(「成功」起來,而不是「失敗」),或者這不是「假設」以這種方式工作。如果不是,你將如何解決它?

回答

5

您看到的行爲可能是邊緣案例錯誤,或者甚至可能是正確的,如果不直觀的話。通常,當你同步調用一個異步方法時,它會繞過一個任務執行,並且由於沒有人等待任務完成,所以異常不會將其傳遞到主線程。如果你直接調用Main,它會成功,但是你的運行時會在另一個線程上看到「成功」的異常。

因爲main是應用程序的入口點,所以它會被同步調用,並且可能因爲入口點不會觸發任務包裝行爲,所以await不能正常運行,並且TaskEx.Run會在自己的線程上拋出,它在運行時顯示爲另一個線程拋出的異常。

如果您要運行主要爲async方法,即返回Task(因爲它返回void真的只能通過await被稱爲async),並從同步的主要方面阻止它,你會得到適當的行爲如下面的測試所示:

static async Task Main() { 
    try { 
     await TaskEx.Run(() => { throw new Exception("failure"); }); 
    } catch(Exception) { 
     throw new Exception("success"); 
    } 
} 

static async Task Main2() { 
    await Main(); 
} 

[Test] 
public void CallViaAwait() { 
    var t = Main2(); 
    try { 
     t.Wait(); 
     Assert.Fail("didn't throw"); 
    } catch(AggregateException e) { 
     Assert.AreEqual("success",e.InnerException.Message); 
    } 
    } 


[Test] 
public void CallDirectly() { 
    var t = Main(); 
    try { 
     t.Wait(); 
     Assert.Fail("didn't throw"); 
    } catch(AggregateException e) { 
     Assert.AreEqual("success", e.InnerException.Message); 
    } 
} 

iee該任務故障爲AggregateException,其中包含成功異常,因爲它是內部異常。

+0

它來自一個控制檯應用程序,用於測試異步,所以頂級方法是我的情況下的主要方法。 – 2011-06-16 21:58:38

+0

@Bent我已經更新了答案,以反映你如何調用,這可能是也可能不是錯誤,但是由'async'入口點引起的未定義行爲 – 2011-06-18 16:25:22