Das Crawlen von HttpClient führt zu einem Speicherverlust

Ich arbeite an einem WebCrawlerImplementierung Es liegt jedoch ein merkwürdiger Speicherverlust im HttpClient der ASP.NET-Web-API vor.

Die gekürzte Version ist also hier:

[UPDATE 2]

Ich habe das Problem gefunden und es ist nicht HttpClient, der undicht ist. Siehe meine Antwort.

[UPDATE 1]

Ich habe hinzugefügt, ohne Wirkung zu entsorgen:

    static void Main(string[] args)
    {
        int waiting = 0;
        const int MaxWaiting = 100;
        var httpClient = new HttpClient();
        foreach (var link in File.ReadAllLines("links.txt"))
        {

            while (waiting>=MaxWaiting)
            {
                Thread.Sleep(1000);
                Console.WriteLine("Waiting ...");
            }
            httpClient.GetAsync(link)
                .ContinueWith(t =>
                                  {
                                      try
                                      {
                                          var httpResponseMessage = t.Result;
                                          if (httpResponseMessage.IsSuccessStatusCode)
                                              httpResponseMessage.Content.LoadIntoBufferAsync()
                                                  .ContinueWith(t2=>
                                                                    {
                                                                        if(t2.IsFaulted)
                                                                        {
                                                                            httpResponseMessage.Dispose();
                                                                            Console.ForegroundColor = ConsoleColor.Magenta;
                                                                            Console.WriteLine(t2.Exception);
                                                                        }
                                                                        else
                                                                        {
                                                                            httpResponseMessage.Content.
                                                                                ReadAsStringAsync()
                                                                                .ContinueWith(t3 =>
                                                                                {
                                                                                    Interlocked.Decrement(ref waiting);

                                                                                    try
                                                                                    {
                                                                                        Console.ForegroundColor = ConsoleColor.White;

                                                                                        Console.WriteLine(httpResponseMessage.RequestMessage.RequestUri);
                                                                                        string s =
                                                                                            t3.Result;

                                                                                    }
                                                                                    catch (Exception ex3)
                                                                                    {
                                                                                        Console.ForegroundColor = ConsoleColor.Yellow;

                                                                                        Console.WriteLine(ex3);
                                                                                    }
                                                                                    httpResponseMessage.Dispose();
                                                                                });                                                                                
                                                                        }
                                                                    }
                                                  );
                                      }
                                      catch(Exception e)
                                      {
                                          Interlocked.Decrement(ref waiting);
                                          Console.ForegroundColor = ConsoleColor.Red;                                             
                                          Console.WriteLine(e);
                                      }
                                  }
                );

            Interlocked.Increment(ref waiting);

        }

        Console.Read();
    }

Die Datei mit den Links ist verfügbarHier.

Dies führt zu einem konstanten Anstieg des Speichers. Die Speicheranalyse zeigt viele Bytes, die möglicherweise vom AsyncCallback gehalten werden. Ich habe schon viele Speicherverluste analysiert, aber dieser scheint auf der HttpClient-Ebene zu sein.

Ich verwende C # 4.0, also keine asynchrone / Warte hier, so dass nur TPL 4.0 verwendet wird.

Der obige Code funktioniert, ist jedoch nicht optimiert und löst manchmal Wutanfälle aus, die jedoch ausreichen, um den Effekt zu reproduzieren. Punkt ist, ich kann keinen Punkt finden, der zu einem Speicherverlust führen könnte.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage