调用 WebAPI 的客户端卡在等待中

本文关键字:在等待 客户端 WebAPI 调用 | 更新日期: 2023-09-27 18:05:45

我有一个调用WebAPI服务的httpclient。GET到达服务并返回内容,但客户端只是一直在等待...

客户端代码:

    static async Task RunAsyncGet(string baseUri, string uri)
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(baseUri);
            HttpResponseMessage response = await client.GetAsync(uri); // <-- stuck here
            response.EnsureSuccessStatusCode();
            if (response.IsSuccessStatusCode)
            {
                IEnumerable<UserAccountModel> users = await response.Content.ReadAsAsync<IEnumerable<UserAccountModel>>();
                //...
            }
        }
    }

网络接口代码:

public class UserAccountController : ApiController
{
    private IRepository _repo;
    public UserAccountController(IRepository repo)
    {
        _repo = repo;
    }
    public HttpResponseMessage Get()
    {
        var s = _repo.GetAllUserAccounts();
        IContentNegotiator negotiator = Configuration.Services.GetContentNegotiator();
        ContentNegotiationResult result = negotiator.Negotiate(typeof(AuthResponseModel), Request, Configuration.Formatters);
        var bestMatchFormatter = result.Formatter;
        var mediaType = result.MediaType.MediaType;
        return new HttpResponseMessage()
        {
            StatusCode = HttpStatusCode.OK,
            Content = new ObjectContent<IQueryable<UserAccount>>(s, bestMatchFormatter, mediaType)
        };
    }
}

思潮?

调用 WebAPI 的客户端卡在等待中

在客户端代码的更上方(无论最终调用RunAsyncGet(,某些代码正在调用Task.WaitTask<T>.Result。如果从 UI 线程调用,这将导致死锁,正如我在博客上解释的那样。

正确的解决方案是更改该Wait/Result以使用await

这就是我最终调用 WebAPI 的方式:

using (HttpClient client = new HttpClient())
{
    client.BaseAddress = new Uri("http://localhost:23302");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    HttpResponseMessage response = client.GetAsync("api/useraccount").Result;
    if (response.IsSuccessStatusCode)
    {
        var t = response.Content.ReadAsAsync<IEnumerable<UserAccount>>().Result;
        ...
    }
    else
    {
        //Something has gone wrong, handle it here
    }
}

看来你打电话给EnsureSuccessStatusCode可能是罪魁祸首。该方法实际上返回一个 HTTP 状态在 200 范围内的HttpResponseMessage,或者将引发异常。因此,您可能需要类似以下内容:

static async Task RunAsyncGet(string baseUri, string uri)
{
    var client = new HttpClient();
    client.BaseAddress = new Uri(baseUri);
    HttpResponseMessage response = await client.GetAsync(uri);
    IEnumerable<UserAccountModel> users = await response.EnsureSuccessStatusCode().Content.ReadAsAsync<IEnumerable<UserAccountModel>>();
    // ... the rest ...
}