我试图从同步方法调用异步方法,并且它一直在轰炸GetUsTraceApiHealth()
,但没有错误。有什么问题?
通话方式:
public ActionResult TestSSN()
{
try
{
var apiResponse = GetUsTraceApiHealth().GetAwaiter().GetResult();
string responseBody = apiResponse.Content.ReadAsStringAsync().Result;
return Json(responseBody, JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
正在调用的方法:
public async Task<HttpResponseMessage> GetUsTraceApiHealth()
{
using (HttpClient httpClient = new HttpClient())
{
try
{
string uri = $"https://trace.{ConfigHelper.SterlingDomain}health?deep";
HttpResponseMessage apiResponse = await httpClient.GetAsync(uri);
return apiResponse;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
}
答案 0 :(得分:5)
按照&#34; async的async mantra一直向下&#34;。基本上,您应该几乎从不在任务上调用.Result
。在大多数情况下,您的调用方法也应该是异步的。然后你可以简单地等待操作的结果:
public async Task<ActionResult> TestSSN()
{
//...
var apiResponse = await GetUsTraceApiHealth();
string responseBody = await apiResponse.Content.ReadAsStringAsync();
//...
}
应该由顶层的应用程序主机(在本例中为ASP.NET和Web服务器)来处理同步上下文。您不应该尝试将异步操作屏蔽为同步操作。
答案 1 :(得分:3)
您的代码的简化版本:
public async Task<ActionResult> TestSSN()
{
var apiResponse = await GetUsTraceApiHealthAsync();
return Json(apiResponse, JsonRequestBehavior.AllowGet);
}
public async Task<string> GetUsTraceApiHealthAsync()
{
using (HttpClient httpClient = new HttpClient())
{
string uri = $"https://trace.{ConfigHelper.SterlingDomain}health?deep";
return apiResponse = await httpClient.GetStringAsync(uri);
}
}
我没有理由退回HttpResponseMessage
以string
的形式阅读其内容,只需使用GetStringAsync
。
此外,永远不要catch
例外来重新抛出它。如果您需要这样做,请使用:
catch(Exception ex)
{
//log or whatever
throw;
}
答案 2 :(得分:0)
您不应该将async
和sync
操作混合在一起。正确执行此操作的方法是将您的方法修改为async
并简单地使用await
;
public async Task<ActionResult> TestSSN()
{
try
{
var apiResponse = await GetUsTraceApiHealth().GetAwaiter().GetResult();
string responseBody = await apiResponse.Content.ReadAsStringAsync().Result;
return Json(responseBody, JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
如果您无法在所有路径中应用async
,则可以使用ConfigureAwait
来防止死锁。
public async Task<HttpResponseMessage> GetUsTraceApiHealth()
{
using (HttpClient httpClient = new HttpClient())
{
try
{
string uri = $"https://trace.{ConfigHelper.SterlingDomain}health?deep";
HttpResponseMessage apiResponse = await httpClient.GetAsync(uri).ConfigureAwait(false);
return apiResponse;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
}