C#异步/等待调用不工作
我试图从同步方法调用异步方法,它一直在调用C#异步/等待调用不工作,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,我试图从同步方法调用异步方法,它一直在调用GetUsTraceApiHealth(),但没有错误。有什么问题 调用方法: public ActionResult TestSSN() { try { var apiResponse = GetUsTraceApiHealth().GetAwaiter().GetResult(); string responseBody = apiResponse.Content.ReadAsStringAsync()
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);
}
}
}
正在调用的方法:
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);
}
}
}
公共异步任务GetUsTraceApiHealth()
{
使用(HttpClient HttpClient=new HttpClient())
{
尝试
{
字符串uri=$”https://trace.{ConfigHelper.SterlingDomain}健康?深”;
HttpResponseMessageAPIResponse=等待httpClient.GetAsync(uri);
返回响应;
}
捕获(例外e)
{
抛出新异常(e.Message);
}
}
}
遵循异步咒语“一路异步”。基本上,您几乎不应该对任务调用
.Result
。在大多数情况下,调用方法也应该是异步的。然后,您只需等待操作结果:
public async Task<ActionResult> TestSSN()
{
//...
var apiResponse = await GetUsTraceApiHealth();
string responseBody = await apiResponse.Content.ReadAsStringAsync();
//...
}
public异步任务TestSSN()
{
//...
var apiResponse=等待GetUsTraceApiHealth();
string ResponseBy=await apiResponse.Content.ReadAsStringAsync();
//...
}
应由顶层的应用程序主机(在本例中为ASP.NET和web服务器)来处理同步上下文。您不应该试图将异步操作屏蔽为同步操作。代码的简化版本:
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);
}
}
您不应该将
async
和sync
操作混合在一起。正确的执行方法是将您的方法装饰为async
,并简单地使用wait
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);
}
}
很可能是僵局。为什么不让
TestSSN()
也异步呢?然后只需等待调用,而不是使用.Result
。使TestSSN
async并让它返回任务。并使用wait
关键字,而不是访问.Response
。不要接受异常,抓取异常的消息,然后抛出一个新异常。这样会丢失有价值的信息。只需完全删除try/catch。旁注:您的catch
块正在丢弃有用的异常信息,并用较少的信息替换它。你真的应该完全摆脱这些。顺便说一句,除非你知道自己在做什么,否则你永远不应该阅读Task.Result
。如果您的代码确保您处于一个任务已经完成的环境中,那么是的,但在其他情况下,则不是。最有可能的情况是死锁。此外,应该删除catch块,让原始异常向上传播调用堆栈。您正在丢弃堆栈跟踪、异常类型、任何附加属性等。请仔细阅读。非常感谢您提供的解决方案(甚至更重要的是解释)。它就像一个符咒!大卫,为什么抓块会“扔掉有用的信息”。我一直认为使用它们是一种最佳实践。@DeanFriedland:首先,你没有用它们做任何事情。仅仅因为您觉得自己应该这样做永远都不是最佳实践,所以将代码放入其中并没有任何用处。在这种特殊情况下,您将剥离所有原始异常,并将其替换为新异常。只有消息被保留。原始异常类型、堆栈跟踪、任何内部异常、原始异常的任何其他属性。。。迷路的只需完全移除这些try/catch结构,它们只会造成伤害,而不会带来任何好处。噢,哇。那么try/catch在任何情况下都有用吗?有没有更好的方法来处理错误?作为一名开发人员,我的职业生涯已经将近2年了,我觉得在我养成坏习惯之前知道这一点非常重要。我非常感谢您的反馈。try/catch结构对于错误处理肯定很有用。但在上面的代码中,您实际上并没有以任何方式处理错误。如果您有一些处理错误的方法,请这样做。但是如果你不打算处理它,就不要抓住一个例外。非常感谢你,卡米洛。我也要试试这个。如果你能留下一个善意的评论,我将很高兴改进我的答案。当然。我感谢你的回应和帮助@迪恩弗里德兰德,谢谢。但我告诉他:)。