The following forum(s) have migrated to Microsoft Q&A (Preview): Developing Universal Windows apps!
Visit Microsoft Q&A (Preview) to post new questions.

Learn More

 locked
[UWP]System.Net.HttpClient memory leak? RRS feed

  • Question

  • I've created a small test application that exhibits a memory leak when using System.Net.HttpClient.GetStringAsync that does not occur with Windows.Web.Http.HttpClient.


    The Diagnostic Tools show an ever increasing number of Task<Windows.Storage.Streams.IBuffer> objects. 

    Am I doing something incorrect (other than the obvious of hammering the web server and forcing garbage collection in this test application)?

    Code below----

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Http;
    using System.Runtime.InteropServices.WindowsRuntime;
    using System.Threading.Tasks;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;

    // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

    namespace App1
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class MainPage : Page
        {
          private static System.Threading.Timer _timer;

          public MainPage()
            {
                this.InitializeComponent();

               // no period on the timer so no chance of overlapping firing

               _timer = new System.Threading.Timer(UpdateData, null, TimeSpan.FromMilliseconds(50),
                TimeSpan.FromMilliseconds(-1));
            }

          // Windows.Web.Http.HttpClient doesn't leak
          // private static Windows.Web.Http.HttpClient client = new Windows.Web.Http.HttpClient();
          private static HttpClient client = new HttpClient();
          private static DateTime lastRequest = DateTime.Now;

           private static string lastResponse;
          private static async void UpdateData(object state)
          {
             lastResponse = await GetData();
          }

           private static async Task<string> GetData()
           {
             var request = String.Format("{0}IsOn?Control=One", "http://192.168.1.160:8082/Rest/");

             client.DefaultRequestHeaders.IfModifiedSince = new DateTimeOffset(lastRequest);
             var response = await client.GetStringAsync(new Uri(request));
             lastRequest = DateTime.Now;

              GC.Collect(); // For testing purposes only
            
             _timer.Change(TimeSpan.FromMilliseconds(50), TimeSpan.FromMilliseconds(-1));
             return response;
          }
        }
    }


    • Edited by Barry Wang Tuesday, May 17, 2016 7:04 AM title tag
    Monday, May 16, 2016 7:40 PM

All replies

  • Hello GrantDavis,

    Is your URI a local URI or it is connecting to a Server. If it is your local machine maybe it is also related to your local method. If it is from the server, I will have to test this issue for you. But I think using Windows.Web.Http.HttpClient is the recommend way to coding in UWP app. Do you have any specific requirement to use the System.NET.Http API?

    Best regards,

    Barry


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, May 17, 2016 10:19 AM
  • Thank you for your response.  I was not aware that Windows.Web.Http was preferred, but I do see the documentation indicates that now.  I probably just took the first ReSharper suggestion when I first typed it or by some other chance chose it.  I can simply continue using it, it's primarily a point of curiosity now.

    The connection is not to my local machine, it is a remote server.  I also tested it without hammering the server, and simply doing a single request to a major website in response to a button click.  A growth of 10-20 of the Task<Windows.Storage.Streams.IBuffer> heap objects was seen with each click.   I would understand if it's just a failure to set some header, I'm just not sure what header that would be.  I tried setting ConnectionClose and that didn't help.

    Thanks,

    Grant

    Tuesday, May 17, 2016 5:58 PM
  • @Grant,

    Thanks for sharing more details back. Yes most of the time using Windows runtime API will be better in the UWP app.

    And for your specific problem, it's a little hard for me to reproduce this without the same environment. I think you may need to try use more uris with different headers to test this issue.

    Anyway, I think you can use the Windows.Web.Http as the solution to this issue.

    And if you need to know the reasons in detail, maybe you can try some technical support channel:

    1. Go to http://aka.ms/storesupport (sign in using your MSDN Subscription if applicable)
    2. Under "App development" click the “Windows 10 Universal app development” OR "Windows 8.x app development” link based on where they are experiencing the problem.
    3. On the next page, choose Problem type = Support for Writing apps, Category = <<appropriate category>>
    4. Then choose the "Start request" link to start a support request.

    Best regards,

    Barry


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, May 19, 2016 9:19 AM
  • Well, it sure isn't worth $500 for me to know why there's a bug, when it should be easy for you to reproduce.  Retrieving this page using GetStringAsync will do it.  Here's the test app to do it.

    https://onedrive.live.com/redir?resid=FF63CD1DEC2E152C!1134116&authkey=!ABCAywH76w9BP1E&ithint=file%2czip

    Press the Leak button, take a memory snapshort.  Press it again, take another.  Watch the number of Task<Windows.Storage.Streams.IBuffer> objects increase.

    Thanks anyway, I guess.

    Thursday, May 19, 2016 2:47 PM
  • @GrantDavis,

    I've used your code but I always got the exception about out of range, so I put the following code to mainpage:

     lastRequest = DateTime.Now;

    Then I got the following result:

    The memory is always 39MB but I can see that the number of Task<Windows.Storage.Streams.IBuffer> increased:

    I will help you consult this case.

    Best regards,

    Barry


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Sunday, May 22, 2016 3:09 AM