How do I cancel all but the last/latest task? For example, suppose I have a time-consuming task that is triggered on a button click. I only want the task from the last button click to run and the previous ones to cancel. Can you show me how this is normally done?
My attempt involves storing all tasks in a list along with their cancellation token and removing them when either the task completes or is cancelled. Creating a list to store both Task and CancellationToken seems like I’m doing too much for what I would’ve thought is a common requirement (eg. a User does a search for something and clicks the search button multiple times. Shouldn’t only the last search be made and all other cancelled?). This is a common scenario, so I’d like to know how this is normally done. What is best practice here?
async void DoStuffAsync()
{
// Store tasks in a list
if (tasksAndCancelTokens == null)
tasksAndCancelTokens = new List<Tuple<Task, CancellationTokenSource>>();
else // we have a new Get request so cancel any previous
tasksAndCancelTokens.ForEach(t => t.Item2.Cancel());
// Create Cancellation Token
var cts = new CancellationTokenSource();
// Method to run asynchonously
Func<int> taskAction = () =>
{
// Something time consuming
Thread.Sleep(5000);
if (cts.Token.IsCancellationRequested)
cts.Token.ThrowIfCancellationRequested();
return 100;
};
// Create Task
Task<int> task = Task<int>.Factory.StartNew(taskAction, cts.Token);
// Create Tuple to store task in list
var tup = new Tuple<Task, CancellationTokenSource>(task, cts);
tasksAndCancelTokens.Add(tup);
try
{
int i = await task;
}
catch (OperationCanceledException)
{
// Don't need to do anything
}
finally
{
tasksAndCancelTokens.Remove(tup);
}
}
Thanks
If you just want to cancel the last task, then that’s all you have to do: