it-swarm.com.ru

Зачем использовать HttpClient для синхронного подключения

Я строю библиотеку классов для взаимодействия с API. Мне нужно вызвать API и обработать ответ XML. Я вижу преимущества использования HttpClient для асинхронного подключения, но то, что я делаю, является чисто синхронным, поэтому я не вижу никаких существенных преимуществ по сравнению с использованием HttpWebRequest.

Если кто-то может пролить свет, я был бы очень признателен. Я не из тех, кто использует новые технологии ради этого.

160
Ketchup

но то, что я делаю, чисто синхронно

Вы можете использовать HttpClient для синхронных запросов просто отлично:

using (var client = new HttpClient())
{
    var response = client.GetAsync("http://google.com").Result;

    if (response.IsSuccessStatusCode)
    {
        var responseContent = response.Content; 

        // by calling .Result you are synchronously reading the result
        string responseString = responseContent.ReadAsStringAsync().Result;

        Console.WriteLine(responseString);
    }
}

Что касается того, почему вы должны использовать HttpClient через WebRequest, то, что ж, HttpClient является новым элементом в блоке и может содержать улучшения по сравнению со старым клиентом.

326
Darin Dimitrov

Я бы повторил ответ Донни В. и Джоша

"Единственная причина, по которой я бы не использовал асинхронную версию, заключается в том, что я пытался поддерживать более старую версию .NET, которая еще не имеет встроенной поддержки асинхронности".

(и upvote, если у меня была репутация.)

Я не могу вспомнить последний раз, если вообще когда-либо, я был благодарен за тот факт, что HttpWebRequest выдал исключения для кодов состояния> = 400. Чтобы обойти эти проблемы, вам нужно немедленно перехватить исключения и сопоставить их с некоторыми механизмами ответов не исключений в вашем коде ... скучно, утомительно и подвержено ошибкам само по себе. Будь то связь с базой данных или реализация сделанного на заказ веб-прокси, "почти" всегда желательно, чтобы драйвер Http просто сообщал вашему коду приложения, что было возвращено, и оставлял вам решать, как себя вести.

Следовательно, HttpClient предпочтительнее.

23
trev

Одна из основных причин, по которой я использую HttpClient, заключается в том, что он не выдает исключение, когда 404 возвращается в URL.

17
Donny V.

Если вы создаете библиотеку классов, то, возможно, пользователи вашей библиотеки захотят использовать вашу библиотеку асинхронно. Я думаю, что это самая главная причина прямо здесь.

Вы также не знаете, как будет использоваться ваша библиотека. Возможно, пользователи будут обрабатывать много-много запросов, и асинхронное выполнение поможет быстрее и эффективнее.

Если вы можете сделать это просто, постарайтесь не обременять пользователей вашей библиотеки, пытаясь сделать поток асинхронным, когда вы можете позаботиться об этом за них.

Единственная причина, по которой я бы не использовал асинхронную версию, заключается в том, что я пытался поддерживать более старую версию .NET, которая еще не имеет встроенной поддержки асинхронности.

6
Josh Smeaton

В моем случае принятый ответ не сработал. Я вызывал API из приложения MVC, у которого не было асинхронных действий.

Вот как мне удалось заставить его работать:

private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);
public static T RunSync<T>(Func<Task<T>> func)
    {           
        CultureInfo cultureUi = CultureInfo.CurrentUICulture;
        CultureInfo culture = CultureInfo.CurrentCulture;
        return _myTaskFactory.StartNew<Task<T>>(delegate
        {
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = cultureUi;
            return func();
        }).Unwrap<T>().GetAwaiter().GetResult();
    }

Тогда я назвал это так:

Helper.RunSync(new Func<Task<ReturnTypeGoesHere>>(async () => await AsyncCallGoesHere(myparameter)));
6
Darkonekt
public static class AsyncHelper  
{
    private static readonly TaskFactory _taskFactory = new
        TaskFactory(CancellationToken.None,
                    TaskCreationOptions.None,
                    TaskContinuationOptions.None,
                    TaskScheduler.Default);

    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();

    public static void RunSync(Func<Task> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();
}

Затем

AsyncHelper.RunSync(() => DoAsyncStuff());

если вы используете этот класс, передайте свой асинхронный метод в качестве параметра, вы можете безопасно вызывать асинхронные методы из методов синхронизации.

это объясняется здесь: https://cpratt.co/async-tips-tricks/

0
Lean Bonaventura