2014-09-03 106 views
3

我有一個奇怪的問題,結合異步/ AWAIT,使其工作: 我創建了一個小程序,它應該基本上處理每一個動作的try/catch語句:異步/等待Lambda表達式

internal static void HandledAction(Action action, Info infoBar) 
    { 
     try 
     { 
      action(); 
     } 
     catch (Exception ex) 
     { 
      infoBar.SetError("An Exception occured: " + ex.Message); 
      WriteLog(ex.StackTrace); 
     } 

Nohing到幻想,但它是值得的,因爲改變錯誤處理是非常容易的。 但是,如果我希望在Lambda中獲得Data async,會發生什麼情況?讓我們這個簡單的例子:

private void mnuImportData_Click(object sender, RoutedEventArgs e) 
    { 
     ActionHelper.HandledAction(async() => 
     { 
      throw new NotImplementedException("Ups"); 
     }, infoMain); 
    } 

肯定的是,HandledAction被調用,傳遞,因爲它得到的指針返回,異常得到投擲,當然沒有處理。

我想我必須創建一個AsyncHandledAction,並將操作設置爲異步,但有沒有更簡單的方法來解決這個問題?

我想很多人使用中央異常處理,並有更好的解決方案呢?

在此先感謝

馬蒂亞斯

編輯:我創建了一個例子,它應該shpw內特我需要:我基本上不想整個動作我通過是awaitable,但在lambda一個電話是:

ActionHelper.HandledActionAsync(() => 
     { 
      //elided 
      CheckFileResult rslt = await excelImport.CheckFilesAsync(tmpPath); 
      //elided 
     }, infoMain); 

當然,這樣做,我得到的錯誤:

錯誤3「等待」經營者只能異步拉姆達明示內使用離子。考慮用'async'修飾符標記這個lambda表達式。的行動代替Func鍵

+2

'async()=> {}'可以匹配'Action'和'Func '。如果它匹配前者,就好像有方法簽名'async void F()';後者,'異步任務F()'。在你的情況下,你正在得到'async void F()',它具有即燃即用語義。 – 2014-09-03 14:43:38

回答

2

與等待

private async void mnuImportData_Click(object sender, RoutedEventArgs e) 
{ 
    await ActionHelper.HandledAction(async() => 
    { 
     throw new NotImplementedException("Ups"); 
    }, infoMain); 
} 
5

的原因是你需要HandleAction

internal static async Task HandledAction(Func<Task> action, Info infoBar) 
{ 
    try 
    { 
     await action(); 
    } 
    catch (Exception ex) 
    { 
     infoBar.SetError("An Exception occured: " + ex.Message); 
     WriteLog(ex.StackTrace); 
    } 
} 

的異步版本,當然,你要調用的方法。既然你:

async() => 
     { 
      throw new NotImplementedException("Ups"); 
     } 

其實是:

async void Method() { } 

Func<Task>是:

async Task Method() { } 

異步無效將捕獲SynchronizationContext.Current,當異常被拋出,將被SynchronizationContext.Post()發佈到SynchronizationContext - (在Windows運行時你可以捕獲這些類型的異常)。在ASP.NET/Console application的情況下SynchronizationContext.Current返回null,這意味着異常將傳播到線程池,我不知道,但我認爲它是不可能的。但是,當異步方法返回Task時,可以通過此返回的任務將異常封送到調用方。還值得一提的是,異步lambda表達式總是會優於方法Func<Task>而不是Action。一般規則是:從不使用async voidasync Action),除非它是「頂級方法」(在示例事件處理程序中)。

+0

我認爲這不是什麼大問題,因爲整個事情的想法就是處理所有異常 – 2014-09-03 15:25:44

+0

除非您有Func /async任務方法,否則無法捕捉任何異常。 – fex 2014-09-03 15:34:09

+0

我想我知道了,就像Stilgar說的那樣,我基本上需要將異步映射到呼叫,並且我需要一個Func 來獲得例外,謝謝至此 – 2014-09-04 06:58:05