我有一个奇怪的问题,结合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);
}
看起来很花哨,但是因为改变错误处理非常容易。 但是,如果我想在Lambda中获得数据异步,会发生什么?让我们举一个简单的例子:
private void mnuImportData_Click(object sender, RoutedEventArgs e)
{
ActionHelper.HandledAction(async () =>
{
throw new NotImplementedException("Ups");
}, infoMain);
}
当然,HandledAction被调用,传递,因为它将指针返回,并且异常被抛出,当然不会被处理。
我想我必须创建一个AsyncHandledAction,并设置动作异步,但有没有更简单的方法来解决这个问题?
我想很多人都使用中央异常处理,并且有更好的解决方案吗?
提前致谢
的Matthias
编辑:我创建了一个示例,这应该是我需要的内容:我基本上不希望我传递的整个Action都是等待的,但Lambda中的一个调用是:
ActionHelper.HandledActionAsync(() =>
{
//elided
CheckFileResult rslt = await excelImport.CheckFilesAsync(tmpPath);
//elided
}, infoMain);
当然,通过这样做,我得到错误:
错误3' await'运算符只能在异步lambda表达式中使用。考虑使用' async'标记这个lambda表达式。改性剂。
答案 0 :(得分:5)
原因是:操作而不是 Func 。既然你的:
async () =>
{
throw new NotImplementedException("Ups");
}
实际上是:
async void Method() { }
Func<Task>
时:
async Task Method() { }
Async void将捕获SynchronizationContext.Current
,当抛出异常时,它将由SynchronizationContext
发布到SynchronizationContext.Post()
- (在Windows运行时,您可以捕获这些类型的异常)。如果ASP.NET/Console application
SynchronizationContext.Current
返回null,这意味着异常将传播到线程池,我不确定,但我认为不可能捕获它。但是,当异步方法返回Task
时,异常可以通过此返回的任务封送到调用方。还值得一提的是,异步lambda表达式总是更喜欢Func<Task>
超过Action
的方法。一般规则是:永远不要使用async void
(async Action
),除非它是&#34;顶级方法&#34; (在示例事件处理程序中)。
答案 1 :(得分:2)
您需要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);
}
}
当然你应该用等待
来调用方法private async void mnuImportData_Click(object sender, RoutedEventArgs e)
{
await ActionHelper.HandledAction(async () =>
{
throw new NotImplementedException("Ups");
}, infoMain);
}