Async / Await Lambdas

我有一个奇怪的问题,结合async / await使它工作:我创建了一个小程序,它应该基本上处理每个动作的try / catch:

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

看起来很花哨,但它的价值很高,因为改变error handling非常容易。 但是,如果我想在Lambda中获取数据异步,会发生什么? 让我们举一个简单的例子:

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

当然,HandledAction被调用,传递,因为它返回指针,exception被抛出,当然不会被处理。

我想我必须创建一个AsyncHandledAction,并设置动作异步,但有没有更简单的方法来解决这个问题?

我想很多人都使用中央exception处理,并且有更好的解决方案吗?

提前致谢

马蒂亚斯

编辑:我创建了一个例子,它应该shpw netter我需要:我基本上不希望我传递的整个Action是等待的,但Lambda中的一个调用是:

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

当然,通过这样做,我得到错误:

错误3’await’运算符只能在异步lambda表达式中使用。 考虑使用’async’修饰符标记此lambda表达式。

您需要HandleAction的异步版本

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

当然你应该用await调用方法

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

原因是: 行动而不是Func 。 既然你的:

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

实际上是:

 async void Method() { } 

Func是:

 async Task Method() { } 

Async void将捕获SynchronizationContext.Current ,当抛出exception时,它将由SynchronizationContext.Post()发布到SynchronizationContext – (在Windows运行时,您可以捕获这些类型的exception)。 在ASP.NET/Console application情况下, SynchronizationContext.Current返回null,这意味着exception将传播到线程池,我不确定,但我认为不可能捕获它。 但是当异步方法返回Task ,exception可以通过返回的Task封送给调用者。 还值得一提的是,异步lambda表达式总是更喜欢使用Func over Action 。 一般规则是:永远不要使用async voidasync Action ),除非它是“顶级方法”(在示例事件处理程序中)。