且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

需要帮助的HttpClient的和WebClient的决定

更新时间:2023-02-16 20:47:16

我住在这两个F#和Web API的世界。

有很多的好东西发生在Web API,特别是在安全性消息处理程序等。

的形式

我知道我只有一个意见,但我只推荐使用的HttpClient 为今后的任何工作。也许有一些方法来利用一些其他的作品走出 System.Net.Http 而不直接使用该程序集,但我无法想象如何将工作在这个时候。

说起比较这两个

  • 在HttpClient的比Web客户端更接近于HTTP。
  • 的HttpClient并不意味着完全取代Web客户端的,因为有像报告进展情况,自定义的URI方案,使FTP调用Web客户端提供 - 但HttpClient的不

需要帮助的HttpClient的和WebClient的决定

如果您使用的是.NET 4.5,请不要使用异步善良与HttpClient的,微软提供给开发商。 HttpClient的是非常对称的HTTP那些Htt的prequest和Htt的presponse。

服务器端的弟兄

更新:5理由使用新的HttpClient API

强类型头。 共享缓存,cookie和证书 访问饼干和共享饼干 控制缓存与共享缓存。 注入你code模块插入到ASP.NET管道。清洁和模块化code。

参考

C#5.0约瑟夫阿尔巴哈利

(Channel9的 - 视频生成2013)

五大理由使用新的HttpClient API连接到Web服务一>

Our web app is running in .Net Framework 4.0. The UI calls controller methods through ajax calls.

We need to consume REST service from our vendor. I am evaluating the best way to call REST service in .Net 4.0. The REST service requires Basic Authentication Scheme and it can return data in both XML and JSON. There is no requirement for uploading/downloading huge data and I don't see anything in future. I took a look at few open source code projects for REST consumption and didn't find any value in those to justify additional dependency in the project. Started to evaluate WebClient and HttpClient. I downloaded HttpClient for .Net 4.0 from NuGet.

I searched for differences between WebClient and HttpClient and this site mentioned that single HttpClient can handle concurrent calls and it can reuse resolved DNS, cookie config and authentication. I am yet to see practical values that we may gain due to the differences.

I did a quick performance test to find how WebClient (sync calls), HttpClient (sync and async) perform. and here are the results:

Using same HttpClient instance for all the requests (min - max)

WebClient sync: 8 ms - 167 ms
HttpClient sync: 3 ms - 7228 ms
HttpClient async: 985 - 10405 ms

Using a new HttpClient for each request (min - max)

WebClient sync: 4 ms - 297 ms
HttpClient sync: 3 ms - 7953 ms
HttpClient async: 1027 - 10834 ms

Code

public class AHNData
{
    public int i;
    public string str;
}

public class Program
{
    public static HttpClient httpClient = new HttpClient();
    private static readonly string _url = "http://localhost:9000/api/values/";

    public static void Main(string[] args)
    {
       #region "Trace"
       Trace.Listeners.Clear();

       TextWriterTraceListener twtl = new TextWriterTraceListener(
           "C:\\Temp\\REST_Test.txt");
       twtl.Name = "TextLogger";
       twtl.TraceOutputOptions = TraceOptions.ThreadId | TraceOptions.DateTime;

       ConsoleTraceListener ctl = new ConsoleTraceListener(false);
       ctl.TraceOutputOptions = TraceOptions.DateTime;

       Trace.Listeners.Add(twtl);
       Trace.Listeners.Add(ctl);
       Trace.AutoFlush = true;
       #endregion

       int batchSize = 1000;

       ParallelOptions parallelOptions = new ParallelOptions();
       parallelOptions.MaxDegreeOfParallelism = batchSize;

       ServicePointManager.DefaultConnectionLimit = 1000000;

       Parallel.For(0, batchSize, parallelOptions,
           j =>
           {
               Stopwatch sw1 = Stopwatch.StartNew();
               GetDataFromHttpClientAsync<List<AHNData>>(sw1);
           });
       Parallel.For(0, batchSize, parallelOptions,
            j =>
            {
                Stopwatch sw1 = Stopwatch.StartNew();
                GetDataFromHttpClientSync<List<AHNData>>(sw1);
            });
       Parallel.For(0, batchSize, parallelOptions,
            j =>
            {
                using (WebClient client = new WebClient())
                {
                   Stopwatch sw = Stopwatch.StartNew();
                   byte[] arr = client.DownloadData(_url);
                   sw.Stop();

                   Trace.WriteLine("WebClient Sync " + sw.ElapsedMilliseconds);
                }
           });

           Console.Read();
        }

        public static T GetDataFromWebClient<T>()
        {
            using (var webClient = new WebClient())
            {
                webClient.BaseAddress = _url;
                return JsonConvert.DeserializeObject<T>(
                    webClient.DownloadString(_url));
            }
        }

        public static void GetDataFromHttpClientSync<T>(Stopwatch sw)
        {
            HttpClient httpClient = new HttpClient();
            var response = httpClient.GetAsync(_url).Result;
            var obj = JsonConvert.DeserializeObject<T>(
                response.Content.ReadAsStringAsync().Result);
            sw.Stop();

            Trace.WriteLine("HttpClient Sync " + sw.ElapsedMilliseconds);
        }

        public static void GetDataFromHttpClientAsync<T>(Stopwatch sw)
        {
           HttpClient httpClient = new HttpClient();
           var response = httpClient.GetAsync(_url).ContinueWith(
              (a) => {
                 JsonConvert.DeserializeObject<T>(
                    a.Result.Content.ReadAsStringAsync().Result);
                 sw.Stop();
                 Trace.WriteLine("HttpClient Async " + sw.ElapsedMilliseconds);
              }, TaskContinuationOptions.None);
        }
    }
}

My Questions

  1. The REST calls return in 3-4s which is acceptable. Calls to REST service are initiated in controller methods which gets invoked from ajax calls. To begin with, the calls run in a different thread and doesn't block UI. So, can I just stick with sync calls?
  2. The above code was run in my localbox. In prod setup, DNS and proxy lookup will be involved. Is there any advantage of using HttpClient over WebClient?
  3. Is HttpClient concurrency better than WebClient ? From the test results, I see WebClient sync calls perform better.
  4. Will HttpClient be a better design choice if we upgrade to .Net 4.5? Performance is the key design factor.

I live in both the F# and Web API worlds.

There's a lot of good stuff happening with Web API, especially in the form of message handlers for security, etc.

I know mine is only one opinion, but I would only recommend use of HttpClient for any future work. Perhaps there's some way to leverage some of the other pieces coming out of System.Net.Http without using that assembly directly, but I cannot imagine how that would work at this time.

Speak­ing of com­par­ing these two

  • Http­Client is more closer to HTTP than Web­Client.
  • Http­Client was not meant to be a com­plete replace­ment of Web Client, since there are things like report progress, cus­tom URI scheme and mak­ing FTP calls that Web­Client pro­vides — but Http­Client doesn’t.

If you’re using .NET 4.5, please do use the async good­ness with Http­Client that Microsoft pro­vides to the devel­op­ers. Http­Client is very sym­met­ri­cal to the server side brethren of the HTTP those are HttpRe­quest and HttpResponse.

Update: 5 Rea­sons to use new Http­Client API

Strongly typed headers. Shared Caches, cook­ies and credentials Access to cook­ies and shared cookies Con­trol over caching and shared cache. Inject your code mod­ule into the ASP.NET pipeline. Cleaner and mod­u­lar code.

Ref­er­ence

C# 5.0 Joseph Albahari

(Channel9 — Video Build 2013)

Five Great Reasons to Use the New HttpClient API to Connect to Web Services