web-dev-qa-db-fra.com

Pourquoi utiliser HttpClient pour la connexion synchrone

Je construis une bibliothèque de classes pour interagir avec une API. J'ai besoin d'appeler l'API et de traiter la réponse XML. Je peux voir les avantages de l'utilisation de HttpClient pour la connectivité asynchrone, mais ce que je fais est purement synchrone. Je ne vois donc aucun avantage significatif à utiliser HttpWebRequest.

Si quelqu'un pouvait nous éclairer, je l'apprécierais beaucoup. Je ne suis pas du genre à utiliser les nouvelles technologies pour le plaisir de les utiliser.

166
Ketchup

mais ce que je fais est purement synchrone

Vous pouvez utiliser HttpClient pour les requêtes synchrones très bien:

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);
    }
}

En ce qui concerne les raisons pour lesquelles vous devriez utiliser HttpClient sur WebRequest, eh bien, HttpClient est le nouvel enfant du bloc et pourrait contenir des améliorations par rapport à l'ancien client.

338
Darin Dimitrov

Je répète Donny V. répondre et Josh

"La seule raison pour laquelle je n'utiliserais pas la version async, c'est si j'essayais de prendre en charge une version plus ancienne de .NET qui ne dispose pas déjà d'une prise en charge async intégrée."

(et upvote si j'avais la réputation.)

Je ne me souviens plus de la dernière fois, si jamais, je suis reconnaissant au fait que HttpWebRequest a lancé des exceptions pour les codes d'état> = 400. Pour résoudre ces problèmes, vous devez intercepter immédiatement les exceptions et les mapper sur des mécanismes de réponse autres que des exceptions. dans votre code ... ennuyeux, fastidieux et sujet aux erreurs en soi. Qu'il s'agisse de communiquer avec une base de données ou d'implémenter un proxy Web sur mesure, il est "presque" toujours souhaitable que le pilote Http indique simplement au code de votre application ce qui a été renvoyé, et vous laisse le soin de décider de son comportement.

Par conséquent, HttpClient est préférable.

25
trev

La principale raison pour laquelle j'utilise HttpClient est qu'il ne lève pas d'exception lorsqu'un 404 est renvoyé sur une URL.

17
Donny V.

Si vous construisez une bibliothèque de classes, les utilisateurs de votre bibliothèque voudront peut-être utiliser votre bibliothèque de manière asynchrone. Je pense que c'est la principale raison ici.

Vous ne savez pas non plus comment votre bibliothèque va être utilisée. Peut-être que les utilisateurs vont traiter de nombreuses demandes, et cela de manière asynchrone l'aidera à fonctionner plus rapidement et plus efficacement.

Si vous pouvez le faire simplement, essayez de ne pas alourdir les utilisateurs de votre bibliothèque et d'essayer de rendre le flux asynchrone lorsque vous pourrez vous en occuper.

La seule raison pour laquelle je n'utiliserais pas la version async, c'est si j'essayais de prendre en charge une version plus ancienne de .NET qui ne dispose pas déjà d'une prise en charge async intégrée.

6
Josh Smeaton

Dans mon cas, la réponse acceptée n'a pas fonctionné. J'appelais l'API depuis une application MVC qui ne comportait aucune action asynchrone.

Voici comment j'ai réussi à le faire fonctionner:

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();
    }

Puis j'ai appelé ça comme ça:

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();
}

Ensuite

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

si vous utilisez cette classe en passant votre méthode async en paramètre, vous pouvez appeler les méthodes async à partir de méthodes de synchronisation de manière sécurisée.

c'est expliqué ici: https://cpratt.co/async-tips-tricks/

0
Lean Bonaventura