Estoy tratando de llamar a un método asíncrono desde un método sincrónico y sigue bombardeando la llamada a GetUsTraceApiHealth()
pero sin errores. ¿Cuál es el problema?
Método de llamada:
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);
}
}
Método que se llama:
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);
}
}
}
3 respuestas
Siga el mantra asíncrono de "asíncrono hasta el final". Básicamente, debería casi nunca llamar a .Result
en una tarea. En la mayoría de los casos, su método de llamada también debe ser asíncrono. Entonces simplemente puede esperar el resultado de la operación:
public async Task<ActionResult> TestSSN()
{
//...
var apiResponse = await GetUsTraceApiHealth();
string responseBody = await apiResponse.Content.ReadAsStringAsync();
//...
}
Debería corresponder al host de la aplicación en el nivel superior (en este caso, ASP.NET y el servidor web) para manejar el contexto de sincronización. No debe intentar enmascarar una operación asincrónica como una sincrónica.
Versión simplificada de su código:
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);
}
}
No hay ninguna razón para devolver el HttpResponseMessage
para leer su contenido como string
, solo use GetStringAsync
.
Además, nunca catch
sea una excepción solo para volver a lanzarlo. Si necesita hacer eso, use:
catch(Exception ex)
{
//log or whatever
throw;
}
No debe mezclar las operaciones async
y sync
juntas. La forma correcta de realizarlo es decorando sus métodos como async
y simplemente usando 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);
}
}
Si no puede aplicar async
en todas las rutas, puede usar ConfigureAwait
para evitar un punto muerto.
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);
}
}
}
Preguntas relacionadas
Nuevas preguntas
c#
C # (pronunciado "see sharp") es un lenguaje de programación multi-paradigma de alto nivel, estáticamente tipado desarrollado por Microsoft. El código C # generalmente se dirige a la familia de herramientas y tiempos de ejecución .NET de Microsoft, que incluyen .NET Framework, .NET Core y Xamarin, entre otros. Use esta etiqueta para preguntas sobre el código escrito en las especificaciones formales de C # o C #.