C# .NET HttpClient在使用wait关键字时挂起?
在考虑了这个有趣的答案之后,我仍然有一种情况,即当我使用wait(下面的示例代码)时,我的HttpClient没有返回。此外我从asp.net MVC5控制器(UI驱动)和WebApi中使用此帮助程序例程。我能做些什么来:C# .NET HttpClient在使用wait关键字时挂起?,c#,asynchronous,asp.net-mvc-5,async-await,task-parallel-library,C#,Asynchronous,Asp.net Mvc 5,Async Await,Task Parallel Library,在考虑了这个有趣的答案之后,我仍然有一种情况,即当我使用wait(下面的示例代码)时,我的HttpClient没有返回。此外我从asp.net MVC5控制器(UI驱动)和WebApi中使用此帮助程序例程。我能做些什么来: 使用wait而不是(可怕的)。结果是否仍然有此函数返回 从MVC控制器和WebApi重用相同的例程 显然,我应该将.Result替换为.ConfigureAwait(false),但这似乎与上面引用的文章中的“Task4”与await httpClient.GetAsync配
public static async Task<IEnumerable<TcMarketUserFullV1>> TcSearchMultiUsersAsync(string elasticQuery)
{
if (string.IsNullOrEmpty(elasticQuery)) return null;
IEnumerable<TcMarketUserFullV1> res = null;
using (var hclient = new HttpClient())
{
hclient.BaseAddress = new Uri("https://addr.servicex.com");
hclient.DefaultRequestHeaders.Accept.Clear();
hclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
hclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",
CloudConfigurationManager.GetSetting("jwt-bearer-token"));
// Why does this never return when await is used?
HttpResponseMessage response = hclient.GetAsync("api/v2/users?q=" + elasticQuery + "&search_engine=v2").Result;
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
res = JsonConvert.DeserializeObject<TcMarketUserFullV1[]>(content).AsEnumerable();
}
else{log.Warn("...");}
}
return res;
}
公共静态异步任务TcSearchMultiUsersAsync(字符串elasticQuery)
{
if(string.IsNullOrEmpty(elasticQuery))返回null;
IEnumerable res=null;
使用(var hclient=new HttpClient())
{
hclient.BaseAddress=新Uri(“https://addr.servicex.com");
hclient.DefaultRequestHeaders.Accept.Clear();
hclient.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);
hclient.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“承载人”,
GetSetting(“jwt承载令牌”);
//为什么在使用wait时,此选项永远不会返回?
HttpResponseMessage response=hclient.GetAsync(“api/v2/users?q=“+elasticQuery+”&search_engine=v2”)。结果;
if(响应。IsSuccessStatusCode)
{
var content=await response.content.ReadAsStringAsync();
res=JsonConvert.DeserializeObject(content.AsEnumerable();
}
else{log.Warn(“…”);}
}
返回res;
}
更新:我的呼叫链,以Telerik Kendo Mvc开头。网格数据绑定呼叫如下:
[HttpPost]
public async Task<ActionResult> TopLicenseGrid_Read([DataSourceRequest]DataSourceRequest request)
{
var res = await GetLicenseInfo();
return Json(res.ToDataSourceResult(request)); // Kendo.Mvc.Extensions.DataSourceRequest
}
[HttpPost]
公共异步任务TopLicenseGrid_读取([DataSourceRequest]DataSourceRequest请求)
{
var res=等待GetLicenseInfo();
返回Json(res.ToDataSourceResult(request));//Kendo.Mvc.Extensions.DataSourceRequest
}
然后:
private异步任务GetLicenseInfo()
{
...
//永不回头
var qry=@“app_metadata.tc_app_user.country:“DE”;
返回等待TcSearchMultiUsersAsync(qry);
}
然后,上面完整显示的例程,但现在没有。结果:
public static async Task<IEnumerable<TcMarketUserFullV1>> TcSearchMultiUsersAsync(string elasticQuery)
{
if (string.IsNullOrEmpty(elasticQuery)) return null;
IEnumerable<TcMarketUserFullV1> res = null;
using (var hclient = new HttpClient())
{
hclient.BaseAddress = new Uri("https://addr.servicex.com");
hclient.DefaultRequestHeaders.Accept.Clear();
hclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
hclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",
CloudConfigurationManager.GetSetting("jwt-bearer-token"));
// This now returns fine
HttpResponseMessage response = hclient.GetAsync("api/v2/users?search_engine=v2&q=" + elasticQuery");
if (response.IsSuccessStatusCode)
{
// This returns my results fine too
var content = await response.Content.ReadAsStringAsync();
// The following line never returns results. When debugging, everything flows perfectly until I reach the following line, which never
// returns and the debugger returns me immediately to the top level HttpPost with a result of null.
res = JsonConvert.DeserializeObject<TcMarketUserFullV1[]>(content).AsEnumerable();
}
else{log.Warn("...");}
}
return res;
}
公共静态异步任务TcSearchMultiUsersAsync(字符串elasticQuery)
{
if(string.IsNullOrEmpty(elasticQuery))返回null;
IEnumerable res=空;
使用(var hclient=new HttpClient())
{
hclient.BaseAddress=新Uri(“https://addr.servicex.com");
hclient.DefaultRequestHeaders.Accept.Clear();
hclient.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);
hclient.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“承载人”,
GetSetting(“jwt承载令牌”);
//现在恢复正常了
HttpResponseMessage response=hclient.GetAsync(“api/v2/users?search_engine=v2&q=“+elasticQuery”);
if(响应。IsSuccessStatusCode)
{
//这也很好地返回了我的结果
var content=await response.content.ReadAsStringAsync();
//下一行永远不会返回结果。调试时,一切都会完美地进行,直到我到达下一行,这一行永远不会返回结果
//返回,调试器立即将我返回到顶层HttpPost,结果为null。
res=JsonConvert.DeserializeObject(content.AsEnumerable();
}
else{log.Warn(“…”);}
}
返回res;
}
你需要等待
一切。你对其中一个等待
是不够的,你需要对所有这些等待
:
这:
应该是:
HttpResponseMessage response = await hclient.GetAsync(
"api/v2/users?q=" + elasticQuery + "&search_engine=v2");
对
.Result
进行一次阻塞调用就足够了,这样就可以死锁。您需要。您需要等待一切。仅对其中一个进行等待
是不够的,您需要对所有这些进行等待
:
这:
应该是:
HttpResponseMessage response = await hclient.GetAsync(
"api/v2/users?q=" + elasticQuery + "&search_engine=v2");
只要对.Result
进行一次阻塞调用就足够了。您需要。谢谢。但这正是我面临的问题,而不是答案。您知道,当我删除.Result和use wait时,它会挂起线程,当我使用.Result时,我至少会从httpClient调用中获得结果。@GGleGrand这听起来特别iar.显示TcSearchMultiUsersAsync的整个调用链顶级操作仍然是ActionResult TopGrid\u Read。更改为公共异步任务TopGrid\u Read似乎已解决。谢谢!我说得太早了。它曾经起作用似乎是侥幸的。我将尝试在原始问题中添加我的调用流和观察结果。可能只是一个计时的东西——即运气=定时炸弹——我们会看到……测试继续。谢谢。但这正是我的问题,而不是答案。你看,当我删除.Result并使用wait时,它挂起线程,当我使用.Result时,我至少会从httpClient调用中得到结果。@GGleGrand这听起来很奇怪。显示整个调用链对于TcSearchMultiUsersAsync
来说,顶级操作仍然是ActionResult TopGrid\u Read。更改为公共异步任务TopGrid\u Read似乎已解决。谢谢!我说得太早了。它曾经起作用似乎是一种侥幸。我将尝试在原始问题中添加我的调用流和观察结果。可能只是时间问题——即运气=定时炸弹--我们将看到…测试继续。您在hclient.SendAsync
中缺少了一个wait
。我知道。这是因为当我将wait放在那里时它会“挂起”。请注意代码行上方的注释。它向我提供返回数据的唯一方法是当我使用(可怕的)时.结果。这就是我不明白的……您缺少一个wait
HttpResponseMessage response = await hclient.GetAsync(
"api/v2/users?q=" + elasticQuery + "&search_engine=v2");