Правильное использование возврата Task.FromException - PullRequest
1 голос
/ 04 июня 2019

Я недавно наблюдал обзор кода между двумя разработчиками.

Был представлен следующий код:

 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), это то, что вы делаете, когда имеете дело с не ожидаемой задачей. В этом случае перехват будет захватывать любое исключение var response = await HttpClient.GetAsync (endpoint); будет бросать. Вы должны просто удалить его и поймать исключение как

Я не совсем понимаю, почему не использовать Task.FromException в этом случае, поэтому у меня есть следующие вопросы:

  1. Что говорит рецензент?
  2. Правильный ли рецензент?
  3. Почему бы не вернуть await Task.FromException?
  4. Каков правильный сценарий возврата await Task.FromException?

Ответы [ 2 ]

2 голосов
/ 04 июня 2019

Рецензент полностью прав.

Единственная ситуация, которую вы использовали бы Task.FromException, - это когда вы находитесь в методе, который вы не можете или не можете реализовать с использованием async и await, и вы хотите, чтобы результат задачи был исключением.

Идиот, но в любом случае:

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

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

Итак, давайте разберемся с вашими вопросами один за другим:

  1. Рецензент говорит, что Task.FromException следует использовать только в не-1016 * / 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-блок.
  4. Не async / await методов, и только это.
1 голос
/ 04 июня 2019
  1. В целом возвращение с улова не является хорошей практикой кодирования.
  2. Task.FromException обычно используется, когда вы хотите положиться на состояние задачи, если выполнено известное условие сбоя. Например, если объект является нулевым, вы знаете, что должны вернуть ошибочную задачу. Клиент может использовать состояние задачи как ошибочную, чтобы показать соответствующее сообщение пользователю. Я изменил код, просто чтобы рассказать вам о примере.

         public async Task<List<Thing>> GetThings()
        {
            try
            {
                var endpoint = $"{Settings.ThingEndpoint}/things";
                var response = await HttpClient.GetAsync(endpoint);
                var obj = JsonConvert.DeserializeObject<List<Thing>>(await response.Content.ReadAsStringAsync());
                if(obj==null)
                {
                  return await Task.FromException<List<Thing>>(new NullRefernceException());
                }
                else
                {     
    
                }
    
            }
            catch (Exception e)
            {
                Log.Logger.Error(e.ToString());
                throw;
    
            }
        }
    
...