Published on

CancellationTokenSource with Timeout in C# (Part 2)

Authors

CancellationTokenSource vs HttpClient.Timeout in ASP.NET Core (Part 2)

We covered how cancellation and timeouts can be dealt with in ASP.NET Core using CancellationTOkenSource in Part 1. Let's compare that approach with HttpClient.Timeout, and have a look at why it is often misunderstood, and look at the alternative we already discussed in Part 1


Using HttpClient.Timeout

HttpClient has a built in timeout implementation.

var client = new HttpClient
{
    Timeout = TimeSpan.FromSeconds(5)
};

await client.GetAsync("https://api.example.com");

It is very convenient, and straight forward. But, it behaves very differently from cooperative cancellation.


Key Differences

AspectCancellationTokenSourceHttpClient.Timeout
Cancellation modelCooperativeForced
Token linkingYesNo
RequestAborted supportYesNo
Downstream cancellationYesNo
Recommended in ASP.NET CoreYesRarely

HttpClient.Timeout only aborts the HTTP request. It does not cancel the rest of your request pipeline.


If you want to abort, due to a timeout, then used a linked cancellation token instead.

Instead of relying on HttpClient.Timeout, use a linked cancellation token:

using var timeoutCts =
    new CancellationTokenSource(TimeSpan.FromSeconds(5));

using var linkedCts =
    CancellationTokenSource.CreateLinkedTokenSource(
        timeoutCts.Token,
        requestToken);

await httpClient.GetAsync(
    "https://api.example.com",
    linkedCts.Token);

This ensures cancellation propagates correctly when:

  • The client disconnects
  • The timeout expires
  • The request pipeline is aborted

A Small Helper Extension

public static class CancellationTokenExtensions
{
    public static CancellationToken WithTimeout(
        this CancellationToken token,
        TimeSpan timeout)
    {
        var timeoutCts = new CancellationTokenSource(timeout);

        return CancellationTokenSource
            .CreateLinkedTokenSource(timeoutCts.Token, token)
            .Token;
    }
}

Usage:

await service.FetchAsync(
    requestToken.WithTimeout(TimeSpan.FromSeconds(5)));

When to Use Which Approach

Use CancellationTokenSource when:

  • You need request cancellation awareness
  • You want predictable cancellation semantics

Use HttpClient.Timeout when:

  • Writing a short-lived console or batch tool
  • No external cancellation exists
  • You need a global safety net only

My conclusion

Relying on CancellationTokenSource instead of HttpClient.Timeout will lead to fewer resource leaks, controlled shutdown behavior, and a more predictable system while under load.