| MAUI-HttpClient-Error-Handling | MAUI-HttpClient-CRUD-Retry | |
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.
The process involves two main objects: the CancellationTokenSource (CTS), which initiates the cancellation, and the CancellationToken, which is passed to the HttpClient methods.
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;
}
}
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
}
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.
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}";
}
}
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);
}
In your Page code-behind:
private void OnCancelClicked(object sender, EventArgs e)
{
_vm.CancelRequest();
}
And in the ViewModel:
public void CancelRequest()
{
_cts?.Cancel();
}
<Button Text="Cancel Request" Clicked="OnCancelClicked" />
| MAUI-HttpClient-Error-Handling | MAUI-HttpClient-CRUD-Retry | |