【问题标题】:Catch exception thrown from an async lambda捕获从异步 lambda 引发的异常
【发布时间】:2014-10-07 21:26:14
【问题描述】:

我正在尝试编写一个方法来尝试执行某个操作,但会吞下引发的任何异常。

我的第一次尝试如下:

public static void SafeExecute(Action actionThatMayThrowException) {
    try {
        actionThatMayThrowException();
    } catch {
        // noop
    }
}

使用同步操作调用时有效:

SafeExecute(() => { 
    throw new Exception(); 
});

但是当使用异步操作调用时失败:

SafeExecute(async () => { 
    await Task.FromResult(0);
    throw new Exception(); 
});

是否可以编写一个处理这两种情况的方法?

【问题讨论】:

  • 你使用的是哪个框架??

标签: c# .net exception-handling task-parallel-library async-await


【解决方案1】:

要正确处理 async 委托,您不应使用 Action(这将导致 lambda 表达式为危险的 async voidshould be avoided),您应该使用 Func<Task> 才能@ 987654327@它:

public static async Task SafeExecute(Func<Task> asyncActionThatMayThrowException)
{
    try
    {
        await asyncActionThatMayThrowException();
    }
    catch
    {
        // noop
    }
}

这将解决async 的情况,但不能解决同步的情况。你不能用一种方法来做这两个。为此,您需要一种不同的方法,但它仍然可以调用 async 来启用重用:

private static readonly Task<object> _completedTask = Task.FromResult<object>(null);

public static void SafeExecute(Action actionThatMayThrowException)
{
    SafeExecute(() =>
    {
        actionThatMayThrowException();
        return _completedTask;
    });
}

我实际上不建议以这种方式忽略未处理的异常。您至少应该考虑记录异常。

【讨论】:

  • 我刚刚意识到我的一些单元测试被这种行为所困扰(基本上失败的 Assert 被吞没了),令人惊讶的是,在这么长时间之后仍然没有任何警告将异步 lambda 分配给 Action。
  • 注意:在较新版本的 .NET 中有 Task.CompletedTask [docs.microsoft.com/en-us/dotnet/api/…
  • 好的,为什么异步 lambda 会抛出调用线程?
猜你喜欢
  • 2013-04-20
  • 2011-07-19
  • 2012-06-05
  • 1970-01-01
  • 1970-01-01
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多