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