232 votes

Pourquoi utiliser HttpClient pour une connexion synchrone ?

Je suis en train de créer une bibliothèque de classes pour interagir avec une API. Je dois appeler l'API et traiter la réponse XML. Je vois les avantages de l'utilisation de HttpClient pour la connectivité asynchrone, mais ce que je fais est purement synchrone, donc je ne vois pas d'avantage significatif à l'utilisation de HttpWebRequest .

Si quelqu'un peut m'éclairer, je lui en serais très reconnaissant. Je ne suis pas du genre à utiliser les nouvelles technologies pour le plaisir.

6 votes

Je suis désolé de vous le dire, mais un appel via HTTP n'est jamais purement synchrone en raison de la manière dont le réseau Windows fonctionne en interne (c.-à-d. les ports d'achèvement).

1 votes

Il est également bon de savoir - Utiliser efficacement async/await avec ASP.NET Web API

424voto

Darin Dimitrov Points 528142

mais ce que je fais est purement synchrone

Vous pouvez utiliser HttpClient pour les demandes synchrones :

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 plus WebRequest est concerné, eh bien, HttpClient est le nouveau venu et pourrait contenir des améliorations par rapport à l'ancien client.

32voto

trev Points 21

Je réitère la réponse de Donny V. et celle de Josh.

"La seule raison pour laquelle je n'utiliserais pas la version asynchrone est que j'essaierais d'une ancienne version de .NET qui n'a pas encore intégré la prise en charge support asynchrone intégré".

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

Je ne me souviens plus de la dernière fois où j'ai apprécié le fait que HttpWebRequest lance des exceptions pour les codes d'état >= 400. Pour contourner ces problèmes, vous devez attraper les exceptions immédiatement et les faire correspondre à des mécanismes de réponse sans exception dans votre code... ce qui est ennuyeux, fastidieux et source d'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 à votre code d'application ce qui a été renvoyé, et vous laisse décider comment vous comporter.

Il est donc préférable d'utiliser HttpClient.

29voto

alexs Points 108

Pour tous ceux qui découvrent ce problème maintenant, la version 5.0 de .NET a ajouté une fonction de synchronisation de l'information. Send à la méthode HttpClient . https://github.com/dotnet/runtime/pull/34948

Les raisons de ce choix ont été longuement discutées ici : https://github.com/dotnet/runtime/issues/32125

Vous pouvez donc l'utiliser à la place de SendAsync . Par exemple

public string GetValue()
{
    var client = new HttpClient();

    var webRequest = new HttpRequestMessage(HttpMethod.Post, "http://your-api.com")
    {
        Content = new StringContent("{ 'some': 'value' }", Encoding.UTF8, "application/json")
    };

    var response = client.Send(webRequest);

    using var reader = new StreamReader(response.Content.ReadAsStream());

    return reader.ReadToEnd();
}

Ce code n'est qu'un exemple simplifié - il n'est pas prêt pour la production.

11voto

Lean Bonaventura Points 381
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();
}

Dans ce cas

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

Si vous utilisez cette classe et passez votre méthode asynchrone en paramètre, vous pouvez appeler les méthodes asynchrones à partir des méthodes synchrones en toute sécurité.

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

8voto

Josh Smeaton Points 18165

Si vous créez une bibliothèque de classes, il se peut que les utilisateurs de votre bibliothèque souhaitent l'utiliser de manière asynchrone. Je pense que c'est la raison la plus importante.

Vous ne savez pas non plus comment votre bibliothèque sera utilisée. Il se peut que les utilisateurs aient à traiter un grand nombre de requêtes, et que le fait de le faire de manière asynchrone leur permette d'être plus rapides et plus efficaces.

Si vous pouvez le faire simplement, essayez de ne pas imposer aux utilisateurs de votre bibliothèque le fardeau de rendre le flux asynchrone alors que vous pouvez vous en charger pour eux.

La seule raison pour laquelle je n'utiliserais pas la version asynchrone est que j'essaierais de prendre en charge une ancienne version de .NET qui ne dispose pas déjà d'un support asynchrone intégré.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X