【问题标题】:HttpClient.GetAsync immediately throws TaskCanceledExceptionHttpClient.GetAsync 立即抛出 TaskCanceledException
【发布时间】:2016-05-31 13:31:25
【问题描述】:

我有一个工作代码从我的 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 逻辑并提供 OOP 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,结合一些代码,但是当断点关闭时它总是抛出错误。我检查了几分钟的超时,它不会导致这个错误。

【问题讨论】:

  • “很明显,提供的代码是相等的。” - 嗯,不,他们不是。在此特定实例中可能没有区别,但在第一个版本中,View 方法被调用之前到达 CommonRestClientusing 语句的结尾,因此该对象是Disposed,而在第二个中,我们知道我们在 using 块之外被调用。正如我所说,这里可能没有区别,但不清楚“代码是否相等”
  • 好吧,我不该这么说,我同意你的看法。
  • 为什么不等client.GetAsync...结束呢?
  • @LeonidMalyshev 因为它没有抛出ObjectDisposedException,这就是为什么我没有发现上下文在请求完成之前结束的原因。我同意这是我的错,但正如我所说,我对Resuest timeout 异常描述感到困惑。这显然不是超时。
  • “很明显,提供的代码是相等的。” -- 为什么GetNodesList 不是async 方法?如果它是 async 并且它在 client.GetAsync 上的 awaited 可能大致相同,就像您展示的第一个 Index 实现一样。从本质上讲,正如您所展示的,您是在客户端有机会完成甚至开始通信之前处理它。

标签: c# .net async-await httpclient


【解决方案1】:

在第二个代码 sn -p 中,客户端在 IO 完成之前被释放。使用第一种形式。

【讨论】:

  • 感谢您的回答。奇怪的是HttpClient 抛出TaskCanceledException 而不是ObjectDisposedException,这就是我感到困惑的原因......
  • @ScottChamberlain 这是有道理的,但是这个异常通常用于取消异常。但是在已处理的客户端上调用方法并不常见,它是一个例外。因此HttpClient 将正常行为与异常行为混为一谈,这在 imo 中并不是一件好事。
  • HttpClient 在我看来常常很奇怪。我习惯于从 .NET Framework 进行更好的设计。就像没有人关心异常一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-07
  • 2014-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多