Previous MAUI-HttpClient-Error-Handling MAUI-HttpClient-CRUD-Retry Next

CancellationToken in .NET MAUI Networking

In .NET MAUI, using a CancellationToken is essential for stopping long-running network requests—such as when a user navigates away from a page or clicks a "Cancel" button—to free up system resources.

🛑 Cancellation Tokens Basics

  • CancellationTokenSource creates a token you can pass into async methods.
  • If the user cancels, the token signals the operation to stop.
  • Works with HttpClient and most async methods in .NET.

🔹 Core Implementation Pattern

The process involves two main objects: the CancellationTokenSource (CTS), which initiates the cancellation, and the CancellationToken, which is passed to the HttpClient methods.

🧩 1. Service Class Logic

Pass the token as the final parameter in your asynchronous methods.

public async Task<string> GetDataAsync(string url, CancellationToken ct)
{
    try 
    {
        // Pass the token directly to the HttpClient method
        var response = await _httpClient.GetAsync(url, ct);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync(ct);
    }
    catch (OperationCanceledException)
    {
        // Handle specifically when the user or timeout cancels the task
        Debug.WriteLine("The network request was cancelled.");
        return null;
    }
}

🧩 2. ViewModel/UI Logic

Manage the lifecycle of the CancellationTokenSource in your ViewModel or Code-behind.

CancellationTokenSource _cts;

async Task LoadData()
{
    // Cancel any existing request before starting a new one
    _cts?.Cancel();
    _cts = new CancellationTokenSource();

    try 
    {
        var data = await _apiService.GetDataAsync("https://api.example.com", _cts.Token);
        // Process data...
    }
    catch (Exception ex)
    {
        // General error handling
    }
}

void OnCancelClicked(object sender, EventArgs e)
{
    _cts?.Cancel(); // This triggers the OperationCanceledException in the task
}

⭐ Key Best Practices

  • Automatic Timeouts: You can set a request-specific timeout by calling _cts.CancelAfter(TimeSpan.FromSeconds(5)).
  • Dispose the CTS: Always dispose of your CancellationTokenSource when the operation is complete or the page is destroyed to avoid memory leaks.
  • Manual Checks: For long loops (e.g., processing a large JSON list), call ct.ThrowIfCancellationRequested() inside the loop to stop execution immediately if the token is cancelled.
  • Android/iOS Sensitivity: Be aware that on some platforms like Android, a cancelled HttpClient request might occasionally throw a WebException or TaskCanceledException depending on the exact timing of the network interruption.

➕ Additional Implementation Tips

  • Use cancellation tokens when navigating between pages to automatically stop background requests.
  • Combine retry logic + cancellation tokens for resilient mobile networking.
  • Log cancellation events for diagnostics and debugging.
  • Use UI indicators (loading spinners + cancel buttons) to improve user experience.

🚀 Advanced Production Recommendations

  • Integrate Polly with HttpClientFactory to add retries, timeouts, and circuit breakers.
  • Implement offline caching with SQLite to reduce unnecessary network calls.
  • Use background sync with cancellation-aware workers.
  • Apply graceful fallback logic when connectivity is lost.

Cancellation Tokens in MAUI REST API Consumer

let’s add cancellation tokens to your REST API consumer so users can cancel long-running requests (like when they navigate away or hit “stop”). This is especially useful in mobile apps where connectivity can be unstable.

🧩 Implementation

1. Add a CancellationTokenSource

In your ViewModel:

private CancellationTokenSource _cts;

public async Task LoadPosts()
{
    _cts = new CancellationTokenSource();

    try
    {
        var posts = await _api.GetPostsAsync(_cts.Token);
        Posts.Clear();
        foreach (var post in posts)
            Posts.Add(post);
        ErrorMessage = string.Empty;
    }
    catch (OperationCanceledException)
    {
        ErrorMessage = "Request was canceled.";
    }
    catch (Exception ex)
    {
        ErrorMessage = $"Could not load posts: {ex.Message}";
    }
}

2. Update ApiService Methods

Pass the token into HttpClient calls:

public async Task<List<Post>> GetPostsAsync(CancellationToken token)
{
    return await _httpClient.GetFromJsonAsync<List<Post>>("posts", token);
}

public async Task<Post> CreatePostAsync(Post newPost, CancellationToken token)
{
    var response = await _httpClient.PostAsJsonAsync("posts", newPost, token);
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadFromJsonAsync<Post>(cancellationToken: token);
}

3. Cancel from the UI

In your Page code-behind:

private void OnCancelClicked(object sender, EventArgs e)
{
    _vm.CancelRequest();
}

And in the ViewModel:

public void CancelRequest()
{
    _cts?.Cancel();
}

4. Add a Cancel Button in XAML

<Button Text="Cancel Request" Clicked="OnCancelClicked" />

✅ Benefits

  • Users can stop requests if they take too long.
  • Prevents wasted bandwidth and battery drain.
  • Keeps the app responsive even under poor connectivity.

➕ Additional Best Practices

  • Reuse a single CancellationTokenSource for multiple related API calls.
  • Always cancel pending requests in OnDisappearing() when navigating away.
  • Combine cancellation tokens with retry logic and timeout policies for maximum resilience.
  • Log cancellation events for diagnostics and performance tuning.

🚀 Production Tips

  • Use IHttpClientFactory with cancellation tokens for scalable enterprise apps.
  • Integrate Polly policies for retries, timeouts, circuit breakers, and cancellation.
  • Gracefully notify users when cancellations occur.
Back to Index
Previous MAUI-HttpClient-Error-Handling MAUI-HttpClient-CRUD-Retry Next
*