正确使用 return Task.FromException

fou*_*der 10 .net c# .net-4.0 task

我最近观察到两个开发人员之间的代码审查。

提交的代码如下:

 public async Task<List<Thing>> GetThings()
    {
        try
        {
            var endpoint = $"{Settings.ThingEndpoint}/things";
            var response = await HttpClient.GetAsync(endpoint);
            return JsonConvert.DeserializeObject<List<Thing>>(await response.Content.ReadAsStringAsync());
        }
        catch (Exception e)
        {
            Log.Logger.Error(e.ToString());
            return await Task.FromException<List<Thing>>(e);
        }
    }
Run Code Online (Sandbox Code Playgroud)

其中收到以下评论:

绝对不需要返回 await Task.FromException>(e),这是您在处理非等待任务时所做的事情。在这种情况下,catch 将捕获任何异常 var response = await HttpClient.GetAsync(endpoint); 会扔。您应该删除它并按原样捕获异常

我不完全理解为什么在这种情况下不使用 Task.FromException,所以我有以下问题:

  1. 审稿人在说什么?
  2. 审稿人正确吗?
  3. 为什么不返回 await Task.FromException?
  4. 返回 await Task.FromException 的正确场景是什么?

ang*_*son 9

审稿人完全正确。

您将使用的唯一情况Task.FromException是,当您处于不能或不会使用asyncand实现的方法中时await,并且您希望任务的结果应该是一个例外。

白痴的例子,但无论如何:

public Task<int> NotReallyAsync()
{
    if (new Random().Next(2) == 0)
        return Task.FromResult(42);

    return Task.FromException<int>(new InvalidOperationException());
}
Run Code Online (Sandbox Code Playgroud)

那么让我们一一处理您的问题:

  1. 评论者说Task.FromException应该只在非async/await方法中使用,在async/await方法中,您应该重新抛出异常:

    catch (Exception e)
    {
        Log.Logger.Error(e.ToString());
        throw;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    或者如果您实现异常过滤器:

    catch (Exception e) when (Log.Logger.ExceptionFilter(e)) { }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 是的,审稿人是对的。

  3. 因为它是不必要的,而只是重新抛出异常。如果你想抛出一个异常,就抛出它。async/的目的await是能够以正常方式编写您的方法,因此请编写正常的 throw 语句或正常的 catch 块。
  4. async/await方法,仅此而已。