2014-09-03 87 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