C# - 为什么我的错误处理包装函数没有捕获异常?

C# - Why is my wrapper function for error handling not catching exceptions?

我正在使用以下一般包装功能:

public static class ErrorHandling
{
    public static void TryCatchErrors<TLogger>(ILogger<TLogger> logger, Action action, string? customMsg = null) => TryCatchErrors<TLogger, object>(logger, () => { action.Invoke(); return 0; }, customMsg);
    public static TOut TryCatchErrors<TLogger, TOut>(ILogger<TLogger> logger, Func<TOut> action, string? customMsg = null)
    {
        try 
        {
            if (logger == null) { throw new ArgumentNullException($"Got null for logger", $"Expected type ILogger<{typeof(TLogger).AssemblyQualifiedName}>!"); }
            if (action == null) { throw new ArgumentNullException($"Got null for action", $"Expected type Func<{typeof(TOut).AssemblyQualifiedName}>!"); }
            return action.Invoke(); 
        }
        catch (Exception e)
        {
            logger.LogError(e, customMsg ?? e.Message);
        }
    }
}

当我执行以下我的预期用法示例时,我的包装函数无法捕获错误:

    public static async Task DeleteRecords<TLog>(ILogger<TLog> _logger) =>
        await ErrorHandling.TryCatchErrors(_logger, async () =>
        {
            // Other functionality that might throw an unexpected error etc.

            throw new Exception();
        });

虽然我在这里遗漏一些愚蠢的东西的可能性绝对是真实的,但我的印象是这与一些我不知道并且一直在努力弄清楚的较低级别的问题或担忧有关我自己。

提前致谢!

那是因为你是直接返回参数Func<TOut> action返回的任务。这意味着任务可能不会在 TryCatchErrors 的 try/catch 内执行。目前它仅通过将任务传递给它的调用者来充当代理。

让它异步并在那里等待它。通过在方法中使其异步并等待它,您正在使其成为状态机的一部分。所以 try/catch 也将是其中的一部分。

public async static TOut TryCatchErrors<TLogger, TOut>(ILogger<TLogger> logger, Func<TOut> action, string? customMsg = null)
{
    try 
    {
        if (logger == null) { throw new ArgumentNullException($"Got null for logger", $"Expected type ILogger<{typeof(TLogger).AssemblyQualifiedName}>!"); }
        if (action == null) { throw new ArgumentNullException($"Got null for action", $"Expected type Func<{typeof(TOut).AssemblyQualifiedName}>!"); }
        await action.Invoke(); 
    }
    catch (Exception e)
    {
        logger.LogError(e, customMsg ?? e.Message);
    }
}

我没有测试它,但我认为你应该将方法签名更改为:

public async static Task<TOut> TryCatchErrors<TLogger, TOut>(ILogger<TLogger> logger, Func<Task<TOut>> action, string? customMsg = null)
{
    try 
    {
        if (logger == null) { throw new ArgumentNullException($"Got null for logger", $"Expected type ILogger<{typeof(TLogger).AssemblyQualifiedName}>!"); }
        if (action == null) { throw new ArgumentNullException($"Got null for action", $"Expected type Func<{typeof(TOut).AssemblyQualifiedName}>!"); }
        await action.Invoke(); 
    }
    catch (Exception e)
    {
        logger.LogError(e, customMsg ?? e.Message);
    }
}

否则你可能不允许等待它。