Search code examples
c#.net-5cancellationtokensource

why CancellationTokenSource.Token.register callback is shared by all request?


I try to understand solution of this channel CancellationTokenSource callback is called for all request In dotnet 5

I have the code bellow

      public class AppTimeout
    {
    ...

    public AppTimeout(RequestDelegate next, IOptions<ServerOptions> options)
    {
...
    }

    public async Task Invoke(HttpContext httpContext)
    {
            var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(httpContext.RequestAborted);
            cancellationTokenSource.CancelAfter(_timeout);

            httpContext.RequestAborted = cancellationTokenSource.Token;
            var requestPath = httpContext.Request.Path;
            cancellationTokenSource.Token.Register(() =>
            {
                logger.Message("... requestPath...");
            });
        await _next(httpContext);
    }
}

After on request have been in timeout, The callback will be triggers for all request

But it is not case and the callback will be called only for the request in timeout just if I replace

cancellationTokenSource.Token.Register(() =>

by

using var registration = cancellationTokenSource.Token.Register(() =>

My question is why ? Could you explain me please?


Solution

  • Without using statements both cancellationTokenSource and registration will continue to be active after the requests ends and eventually you will get a timeout where the callback is invoked even though the request already ended. The timeout is not a timeout of the request. It's a result of a bug in the code. I'm not sure I understand why this only starts to occur after a "real" timeout but I wouldn't waste energy trying to understand that. You have to dispose registration and I believe also cancellationTokenSource when the requests ends (e.g. by using using statements).