Search code examples
c#taskcancellation

cancel async task if running


I have the following method called on several occasions (e.g onkeyup of textbox) which asynchronously filters items in listbox.

private async void filterCats(string category,bool deselect)
{

    List<Category> tempList = new List<Category>();
    //Wait for categories
    var tokenSource = new CancellationTokenSource();
    var token = tokenSource.Token;

    //HERE,CANCEL TASK IF ALREADY RUNNING


    tempList= await _filterCats(category,token);
    //Show results
    CAT_lb_Cats.DataSource = tempList;
    CAT_lb_Cats.DisplayMember = "strCategory";
    CAT_lb_Cats.ValueMember = "idCategory";

}

and the following task

private async Task<List<Category>> _filterCats(string category,CancellationToken token)
{
    List<Category> result = await Task.Run(() =>
    {
        return getCatsByStr(category);
    },token);

    return result;
}

and I would like to test whether the task is already runing and if so cancel it and start it with the new value. I know how to cancel task, but how can I check whether it is already running?


Solution

  • This is the code that I use to do this :

    if (_tokenSource != null)
    {
        _tokenSource.Cancel();
    }
    
    _tokenSource = new CancellationTokenSource();
    
    try
    {
        await loadPrestatieAsync(_bedrijfid, _projectid, _medewerkerid, _prestatieid, _startDate, _endDate, _tokenSource.Token);
    }
    catch (OperationCanceledException ex)
    {
    }
    

    and for the procedure call it is like this (simplified of course) :

    private async Task loadPrestatieAsync(int bedrijfId, int projectid, int medewerkerid, int prestatieid,
            DateTime? startDate, DateTime? endDate, CancellationToken token)
    {
        await Task.Delay(100, token).ConfigureAwait(true);
        try{
            //do stuff
    
            token.ThrowIfCancellationRequested();
    
        }
        catch (OperationCanceledException ex)
        {
           throw;
        }
        catch (Exception Ex)
        {
            throw;
        }
    }
    

    I am doing a delay of 100 ms because the same action is triggered rather quickly and repeatedly, a small postpone of 100 ms makes it look like the GUI is more responsive actually.