Search code examples
c#.nethttplistener

HttpListener blocking when using tasks and task.delay


So doing a personal project to write a simple http server. Nothing fancy. But I wanted to use Tasks to handle the requests. So I wrote the code below and for some reason it's "blocking" but not really?

So I start the server and then with two separate tabs open in chrome I send a request to the server at roughly the same time. So in theory both requests should be finished in roughly 3 secs. However the first tab loads after 3 seconds then the 2nd tab loads 3 seconds after the first one so 6 seconds all together.

Interestingly enough it seems the main thread where the server is running isn't being blocked but the task threads are. The reason I say the main thread isn't blocked is cause it iterates again in the while loop and reaches the writeline for "waiting for connection" immediately after launching HandleRequestAsync. The output looks like this. Seems like it gets blocked on the second call to HandleRequestAsync if the first hasn't finished.

Output

Waiting for connection
Finished Connection
Waiting for connection
Delay over
Finished Connection
Waiting for connection
Delay over

Code

class Server
{
    private HttpListener listener { get; set; }
        
    private async Task HandleRequestAsync(HttpListenerRequest request, HttpListenerResponse response)
    {
        await Task.Delay(3000);
        Console.WriteLine("Delay over");

        response.ContentLength64 = 4;
        response.OutputStream.Write(Encoding.UTF8.GetBytes("Test"));

        response.OutputStream.Close();
    }

    public async Task StartServing()
    {
        listener.Start();

        while(true)
        {
            Console.WriteLine("Waiting for connection");

            var ctx = await listener.GetContextAsync().ConfigureAwait(false);

            HandleRequestAsync(ctx.Request, ctx.Response);

            Console.WriteLine("Finished Connection");
        }
    }
    public Server()
    {
        listener = new HttpListener();
        listener.Prefixes.Add("http://localhost:8000/");
    }
}

Solution

  • As shown in the comments of the question. Chrome and pretty much all web browsers restrict how many concurrent connections can be made to one host even if they are in different tabs.