HttpClient.GetAsync немедленно выдает TaskCanceledException

У меня был рабочий код, который возвращал что-то из моего CommonRestClient (это простая оболочка для HttpClient):

public async Task<IActionResult> Index()
{
    var uri = _baseUri.Concat(AvalancheServiceAdresses.NodeService);
    using (var client = new CommonRestClient(uri))
    {
        var result = await client.GetAsync<List<NodeInfoContract>>(new Uri(NodeServiceConstant.NodesContractUrl, UriKind.Relative), null);
        return View(result);
    }
}

Он работал нормально, и я был счастлив. Пока я не решу переместить свой код из представления в другой класс, который должен инкапсулировать всю логику REST и предоставлять ООП API.

Итак, теперь мой индекс выглядит так:

public async Task<IActionResult> Index()
{
    var nodeInfoContracts = await _configManager.GetNodesList();
    return View(nodeInfoContracts);
}

где GetNodesList

public ConfiguredTaskAwaitable<List<NodeInfoContract>> GetNodesList()
{
    var uri = _baseUri.Concat(AvalancheServiceAdresses.NodeService);
    using (var client = new CommonRestClient(uri))
    {
        return client.GetAsync<List<NodeInfoContract>>(new Uri(NodeServiceConstant.NodesContractUrl, UriKind.Relative), null);
    }
}

Понятно, что предоставленные коды равны.

Но теперь он всегда выдает исключение, когда я пытаюсь получить результат. В моем методе GetAsync он терпит неудачу в следующей строке с TaskCanceledException:

var response = await _client.GetAsync(url).ConfigureAwait(false);

Но это интересно: когда я ставлю точку останова на эту строку и перешагиваю через нее, все работает нормально. Итак, здесь у нас есть состояние гонки или подобное.

Почему я получаю это? Я пытался поставить CondigureAwait false/true, комбинируя какой-то код, но он всегда выдает ошибку, когда точки останова отключены. Я проверил тайм-аут, который составляет несколько минут, это не может вызвать эту ошибку.


person Alex Zhukovskiy    schedule 31.05.2016    source источник
comment
Понятно, что предоставленные коды равны. - ну нет, не они. Это может не иметь значения в этом конкретном случае, но в первой версии метод View вызывается до достижения конца оператора using для CommonRestClient и, таким образом, этот объект Disposed, тогда как во второй , мы знаем, что нас вызывают за пределами блока using. Как я уже сказал, здесь может и не быть разницы, но не ясно, что коды равны   -  person Damien_The_Unbeliever    schedule 31.05.2016
comment
Хорошо, я не должен этого говорить, я согласен с вами.   -  person Alex Zhukovskiy    schedule 31.05.2016
comment
Почему бы не подождать, пока закончится client.GetAsync...?   -  person Leonid Malyshev    schedule 31.05.2016
comment
@LeonidMalyshev, потому что он не выдал ObjectDisposedException, поэтому я не обнаружил, что контекст заканчивается до завершения запроса. Я согласен, что это моя вина, но, как я уже сказал, меня смутило описание исключения Resuest timeout. Это явно был не тайм-аут.   -  person Alex Zhukovskiy    schedule 31.05.2016
comment
Ясно, что предоставленные коды равны. -- почему GetNodesList не является async методом? Это могло бы быть примерно так же, если бы это было async и оно awaited на client.GetAsync, как в первой реализации Index, которую вы показываете. По сути, как вы показываете, вы избавляетесь от клиента до того, как он успевает завершить или даже начать общение.   -  person acelent    schedule 31.05.2016


Ответы (1)


Во втором фрагменте кода клиент удаляется до завершения ввода-вывода. Используйте первую форму.

person usr    schedule 31.05.2016
comment
Спасибо за ответ. Странно, что HttpClient выбрасывает TaskCanceledException вместо ObjectDisposedException, поэтому я и запутался... - person Alex Zhukovskiy; 31.05.2016
comment
@AlexZhukovsky ObjectDisposedException обычно выбрасывается только при первом вводе метода. Отмена более распространена, если он вошел, затем немного поработал, а затем должен закончиться раньше. - person Scott Chamberlain; 31.05.2016
comment
@ScottChamberlain это имеет смысл, но это исключение обычно используется для отмены исключения. Но метод вызова на удаленном клиенте не распространен, это исключение. Таким образом, HttpClient смешивайте нормальное поведение с исключительным, что, по моему мнению, не очень хорошо. - person Alex Zhukovskiy; 31.05.2016
comment
HttpClient часто кажется мне странным. Я привык к лучшему дизайну .NET Framework. Как будто никто не заботился об исключениях. - person usr; 31.05.2016