我正在尝试通过Asynctask使用POST方法调用另一个API。 一切正常(请求正确执行,因为它启动我的SQL请求)但我无法从外部服务器获得任何响应。
我可以看到我不需要运行任务来使其执行但我没有任何结果。
[HttpPost]
public string Post([FromBody]JObject value)
{
if (MesureController.CheckJsonIntegrity<Mesure>(value))
{
var task = MesureAsync(value);
return task.Result;
}
return null;
}
static async Task<string> MesureAsync(JObject value)
{
using (client)
{
string url = ConfigurationManager.AppSettings["internalserver:url"];
var json_string = new Dictionary<string, string>
{
{"json_string", value.ToString() }
};
var content = new FormUrlEncodedContent(json_string);
var response = await client.PostAsync(url + "Mesure/Index", content);
string resultContent = await response.Content.ReadAsStringAsync();
return resultContent;
}
}
答案 0 :(得分:1)
您看到了common deadlock that I describe in more detail on my blog。总之,ASP.NET(完整的,而非Core)代码在&#34;请求上下文中运行&#34;只允许一个线程一次处理一个请求。当MesureAsync
将POST发送到其他API时,它returns an incomplete task。然后,您的Post
方法会阻塞当前线程,等待该任务。稍后,当对其他API的POST完成时,MeasureAsync
会尝试继续执行within that same request context,但它不能,因为Post
已阻止该请求上下文中的某个线程,并且请求上下文一次只允许一个线程。
因此,您最终会Post
占用请求上下文,等待MeasureAsync
完成,MeasureAsync
等待Post
放弃请求上下文,以便它可以完成。经典僵局。
最佳解决方案是"async
all the way",即不要阻止异步代码。在这种情况下,请将Result
替换为await
:
[HttpPost]
public string Post([FromBody]JObject value)
{
if (MesureController.CheckJsonIntegrity<Mesure>(value))
{
return await MesureAsync(value);
}
return null;
}
如果您现在尝试编译它,它会给您一个编译器错误,告诉您如何处理Post
以使其工作:
[HttpPost]
public async Task<string> Post([FromBody]JObject value)
{
if (MesureController.CheckJsonIntegrity<Mesure>(value))
{
return await MesureAsync(value);
}
return null;
}
......你已经完成了!
答案 1 :(得分:0)
由于阻塞和异步代码的混合,原始代码中没有返回结果。
应该将actions语法更新为异步,并允许更好的内容协商。
假设此代码适用于Asp.Net-Core,则操作将更新为
[HttpPost]
public async Task<IActionResult> Post([FromBody]JObject value) {
if (MesureController.CheckJsonIntegrity<Mesure>(value)) {
var measure = await MesureAsync(value);
return Ok(measure);
}
return BadRequest();
}
如果使用WebAPI 2. *然后将IActionResult
更改为IHttpActionResult
,它将以相同的方式工作。
答案 2 :(得分:-1)
您必须确保Task
将会运行。
使用此代码段:
Task.Run(()=>MesureAsync(value)).Result;