C #: разные результаты при использовании синхронизации, асинхронности или асинхронности с общим HttpClient - PullRequest
0 голосов
/ 23 мая 2018

Введение

Я работал в ASP.NET Web API, где столкнулся с некоторыми странными взаимодействиями при попытке вызвать другой API.Я попробовал 3 разных способа использования HttpClient, все с разными результатами.
Протестировал все, используя Postman, отсюда и некоторые результаты.

1.Синхронизация вызова HttpClient

private static string GetAPI(string url)
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri(url);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");

        HttpResponseMessage response = client.GetAsync(url).Result;
        string contents = response.Content.ReadAsStringAsync().Result;

        if (response.IsSuccessStatusCode)
        {
            return contents;
        }
    }

    return null;
}

Результат

Работает , но я хочу использовать async

2.Асинхронный вызов httpClient

private static async Task<string> GetAPI(string url)
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri(url);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");

        HttpResponseMessage response = await client.GetAsync(url);
        string contents = await response.Content.ReadAsStringAsync();

        if (response.IsSuccessStatusCode)
        {
            return contents;
        }
    }

    return null;
}

Результат

Не работает .Не выйдет за черту HttpResponseMessage response = await client.GetAsync(url);, так как ответа никогда не будет?

3.Асинхронный вызов httpClient с общим HttpClient

private static readonly HttpClient client = new HttpClient();

private static async Task<string> GetAPI(string url)
{
    client.BaseAddress = new Uri(url);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");

    HttpResponseMessage response = await client.GetAsync(url);
    string contents = await response.Content.ReadAsStringAsync();

    if (response.IsSuccessStatusCode)
    {
        return contents;
    }

    return null;
}

Результат

Работает один раз .Затем выдаст ошибку: System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: This instance has already started one or more requests. Properties can only be modified before sending the first request. (как предполагает этот SO-ответ ).

Вопрос

Я был бы признателен, если бы кто-то мог объяснить, почему эти результаты такдругой и / или дать альтернативный способ совершить базовый вызов HttpClient (все равно хотелось бы использовать async).

1 Ответ

0 голосов
/ 24 мая 2018

@ Игорь сообщил мне о проблеме взаимоблокировки во втором примере.
Так что в настоящее время я использовал HttpClient как таковой (async):

private static async Task<string> GetAPI(string url)
    {
    // TODO: Use a shared instance of HttpClient
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri(url);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");

        var jsonString = await client.GetStringAsync(url).ConfigureAwait(false);
        return jsonString;
    }
}

Хотя некоторые вещи былиясно, весь вопрос еще не ответил.Я поэтому не приму это как ответ, но хотел бы поблагодарить тех, кто предоставил мне хорошую информацию об использовании HttpClient.

...