C# asynchronous method - help needed

后端 未结 3 1366
逝去的感伤
逝去的感伤 2021-01-17 03:17

I have an asynchronous method that consumes a Web API action. It appears to be stuck in a loop. My reasoning for this is because if I put a break point on line 1 of the catc

相关标签:
3条回答
  • 2021-01-17 03:53

    Are you working in a external library? If so try adding ConfigureAwait(false);

    var response = await _client.GetAsync(string.Format("{0}/api/document", _baseURI))
                                .ConfigureAwait(false);
    

    Its to do with telling await not to capture the current context. Calling ConfigureAwait will ensure the rest of the method is executed using the ThreadPool. Some good reading on the subject can be found here on Stephen Cleary's blog.

    0 讨论(0)
  • 2021-01-17 04:00

    If it works with a web browser but not using code then you probably need to send an accept header. Add the following line

    _client.DefaultRequestHeaders.Accept = new MediaTypeWithQualityHeaderValue("application/json");
    
    0 讨论(0)
  • 2021-01-17 04:02

    Are you calling GetAll().Result from an ASP.NET application? Since you have tagged MVC to this question, I assume so. If you do, then you are deadlocking yourself.

    Say you calling web API like this.

    public ActionResult Index()
    {
        var result = GetAll().Result;
    
        return View();
    }
    

    The problem here is when the async call completes, it needs to continue on the original thread where it jumped out but you are blocking that thread by calling Result(). Call to Result blocks and waits for async call to return and the async continuation waits for the ASP.NET thread to be available to continue. That is a dead lock.

    Change your GetAll() like this.

    public async Task<IEnumerable<Document>> GetAll()
    {
        try
        {
            var response = await _client.GetAsync(
                           string.Format("{0}/api/document", _baseURI))
                               .ConfigureAwait(false);
    
            // never hits line below
            return await response.Content.ReadAsAsync<Document>() 
                       as IEnumerable<Document>;
        }
        catch (Exception ex)
        {
            // handle exception
        }
    }
    

    This indicates the context need not be preserved when the async call is complete and hence the continuation happens in a thread pool thread (not ASP.NET).

    Better yet change the action method to public async Task<ActionResult> Index() and await GetAll().

    If you find this answer helpful, you must only thank Stephen Cleary.

    0 讨论(0)
提交回复
热议问题