DEV Community

Ahmed Fouad
Ahmed Fouad

Posted on • Originally published at Medium on

2 2

How to use CanellationToken With ICommand A Solid Implementation of ICommand

This article can be considered a part 2 of Async Command A Modern Implementation of ICommand in which we were addressing the async problem in ICommand by blocking the CanExecuteStatus to false in case the previous task was not yet completed.

In this article, we will address the same problem using a different way we will use CancellationToken to cancel the pending task and execute the new one, imagine you have a news app where the user should click on one title in a listview the app will download the news article and will show it, what happens when the user clicks on a title and before the download complete he clicks on another one.

public class CommandAsync<T> : ICommand
{
private CancellationTokenSource cancellationTokenSource;
private readonly Func<T, CancellationToken, Task> _executeTask;
private readonly Predicate<T> _canExecute;
private bool _locked;
public CommandAsync(Func<T,CancellationToken, Task> executeTask) : this(executeTask, o => true)
{
}
public CommandAsync(Func<T, CancellationToken, Task> executeTask, Predicate<T> canExecute)
{
cancellationTokenSource = new CancellationTokenSource();
_executeTask = executeTask;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute.Invoke((T)parameter);
}
public async void Execute(object parameter)
{
try
{
if (_locked)
{
cancellationTokenSource.Cancel();
cancellationTokenSource = new CancellationTokenSource();
}
_locked = true;
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
await _executeTask.Invoke((T)parameter, cancellationTokenSource.Token);
}
finally
{
_locked = false;
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public void ChangeCanExecute()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}

And you can use it in your ViewModel like this

CommandAsync<Uri> commandAsync = new CommandAsync<Uri>(async (uri,cancellationToken)=>await client.GetAsync(uri,cancellationToken));

or can be simplified to this

CommandAsync<Uri> commandAsync = new CommandAsync<Uri>(httpclient.GetAsync);

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up