Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#异步/等待调用不工作_C#_.net_Asynchronous_Async Await - Fatal编程技术网

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结构对于错误处理肯定很有用。但在上面的代码中,您实际上并没有以任何方式处理错误。如果您有一些处理错误的方法,请这样做。但是如果你不打算处理它,就不要抓住一个例外。非常感谢你,卡米洛。我也要试试这个。如果你能留下一个善意的评论,我将很高兴改进我的答案。当然。我感谢你的回应和帮助@迪恩弗里德兰德,谢谢。但我告诉他:)。