Search code examples
c#.nettimerasync-awaitput

Throwing exception after a while


I'm connecting to a device using a put command over url. However, the setup requires the command being async to be inside a timer. It runs fine for a while then mscorlib.dll starts throwing exceptions and the commands stop being sent.

I have tried to add async in the timer event handler and await before the function that calls the command but it still happens. Not 100% sure how it should be because the timer cannot wait and this happens very fast.

button click {
_updateTimer = new Timer(_updateInterval);
_updateTimer.Tick += new EventHandler(TimerUpdate_Tick);
Start
}

private async void TimerUpdate_Tick(object sender, System.EventArgs e)
{
   //do other very important stuff that has to be in timer update event
   await myfunction();
}

public static async Task myfunction()
{
    HttpClientHandler handler = new HttpClientHandler();

    using (var httpClient = new HttpClient(handler))
    {
       using (var request = new HttpRequestMessage(new HttpMethod("PUT"), address))
       {
           request.Content = new StringContent("hello");
           var response = await httpClient.SendAsync(request);
           //after some time, it gives an exception on this SendAsync saying connection closed. I did try reconnecting but still gives it again.
        }
    }            
}

What I want is to clear some buffer if that is the issue and keep the connection alive and requests being sent as they do for the first 15 seconds. I'm not sure about the async, awaits and tasks being used correctly.

Thanks


Solution

  • If you're able to execute the requests for a while and then they fail, you may have exhausted the number of available sockets. This can happen when we repeatedly create and dispose an HttpClient for each request.

    Instead we should create the HttpClient and reuse it for as long as possible. Technically we should dispose of it when we're done with it because it implements IDisposable, but we won't be done with it for as long as we keep reusing it. So the proper way to use and dispose it isn't 100% clear.

    The documentation says:

    HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors. Below is an example using HttpClient correctly.

    ... and follows with this example:

    public class GoodController : ApiController
    {
        // OK
        private static readonly HttpClient HttpClient;
    
        static GoodController()
        {
            HttpClient = new HttpClient();
        }
    }
    

    Another alternative is using something other than HttpClient. RestSharp is not only really easy to use but it doesn't use an HttpClient so you don't have to worry about disposing it. It handles a lot of things like that internally.

    Also, here's the fun article that brought this to my attention.