首页 > 解决方案 > 正确使用 return Task.FromException

问题描述

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

提交了以下代码:

 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);
        }
    }

其中收到以下审查意见:

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

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

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

标签: c#.net.net-4.0task

解决方案


审稿人完全正确。

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

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

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

    return Task.FromException<int>(new InvalidOperationException());
}

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

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

    catch (Exception e)
    {
        Log.Logger.Error(e.ToString());
        throw;
    }
    

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

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

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

推荐阅读