Search code examples
c#multithreadingtaskcancellationtokensource

How to cancel a specific task by its ID


I have an WPF application in which I am generating numbers of task for parallel processing. Now when my condition becomes true then I need to cancel particular that task. When I am applying CancellationTokenSource for cancel task then it's cancel whole bunch of task but I need to cancel only single.

Task t1 = Task.Run(() => Task.Delay(30000, token), token);
                test.Add(t1.Id, symbolName);
                lstTask.Add(t1);
                await t1;

here I am holding Task Id so I can know that which Task should I cancel ?

So please can you suggest me that how can I able to cancel only single Task by it's Id ?

After discussion about problem I have made some changes in code so please suggest me that should I change my logic ? because recently I aware that task Id is not unique so I prefer CTS directly.

public static async void startAddToPosition(System.Threading.CancellationTokenSource cts1, string symbolName)
{
          try
          {
               Task t1 = Task.Run(() => Task.Delay(30000, cts1.Token), cts1.Token);
                test.Add(symbolName, cts1);
                lstTask.Add(t1);
                lstCts.Add(cts1);
                await t1;
                generateRealPosition("QQQ"); //here I need symbol name when task will complete it's 30 seconds.
          }
          catch (OperationCanceledException ex)
          {
                var symbolName = test.FirstOrDefault(q => q.Value.Token == ex.CancellationToken).Key;
            }
}

however on the other side when condition become full fill then I am trying to cancel task like below :

CancellationTokenSource cts = Evaluation.parallelScripts.test.FirstOrDefault(q => q.Key == eventData.symbolName).Value;
  cts.Cancel();

So I am trying to get CancellationTokenSource for particular symbol from list and cancelling that CTS. So that task become cancel.

So my question is that I don't know that CTS token is unique or not. because when CTS cancelling Task then in exception I need Symbol Name according to that CTS token.


Solution

  • Each cancellation token source is a separate logical "cancel". As you've found, if you share cancellation tokens, then a that single "cancel" will cancel all of them.

    To create multiple logical "cancel"s, you'll need multiple cancellation token sources:

    CancellationTokenSource cts1 = new CancellationTokenSource();
    Task t1 = Task.Run(() => Task.Delay(30000, cts1.Token), cts1.Token);
    test.Add(t1.Id, symbolName, cts1);
    lstTask.Add(t1);
    lstCts.Add(cts1);
    await t1;
    

    can you suggest me that how can I able to cancel only single Task by it's Id ?

    This is not possible.

    For one, it's not possible to cancel a task from the "outside". All you can do is give it a token and cancel that token. It's up to the task to respond to that token appropriately. This is how cooperative cancellation works.

    There's another reason this isn't possible: task ids are not unique. It appears you are using task ids in your code; I recommend you re-evaluate the design to ensure that it can handle non-unique task ids. Perhaps using the actual Task instance instead (which is unique).