Как отменить конкретную задачу по ее идентификатору - PullRequest
0 голосов
/ 14 мая 2019

У меня есть приложение WPF, в котором я генерирую номера задач для параллельной обработки. Теперь, когда мое состояние становится истинным, мне нужно отменить эту задачу. Когда я применяю CancellationTokenSource для отмены задачи, тогда она отменяет всю группу задач, но мне нужно отменить только одну.

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

здесь я держу идентификатор задачи, чтобы я мог знать, какую задачу мне следует отменить?

Так, пожалуйста, вы можете предложить мне, как я могу отменить только одну задачу по ее идентификатору?

После обсуждения проблемы я внес в код некоторые изменения, поэтому, пожалуйста, предложите мне изменить мою логику? потому что недавно я знал, что идентификатор задачи не уникален, поэтому я предпочитаю CTS напрямую.

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;
            }
}

однако, с другой стороны, когда условие становится полным, тогда я пытаюсь отменить задачу, как показано ниже:

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

Поэтому я пытаюсь получить CancellationTokenSource для определенного символа из списка и отменяю этот CTS. Так что эта задача стала отменой.

Так что мой вопрос в том, что я не знаю, является ли токен CTS уникальным или нет. потому что, когда CTS отменяет задачу, тогда в исключении мне нужно имя символа в соответствии с этим токеном CTS.

Ответы [ 2 ]

0 голосов
/ 14 мая 2019

Каждый источник токена отмены является отдельной логической «отменой». Как вы выяснили, если вы поделитесь токенами отмены, то этот «отмена» отменит все из них.

Чтобы создать несколько логических «отмен», вам понадобится несколько источников токенов отмены:

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;

Можете ли вы предложить мне, как я могу отменить только одну задачу по ее идентификатору?

Это невозможно.

С одной стороны, невозможно отменить задачу извне. Все, что вы можете сделать, это дать ему токен и отменить его. Задача - ответить на этот токен соответствующим образом. Вот как работает совместное аннулирование .

Есть еще одна причина, по которой это невозможно: идентификаторы задач не являются уникальными . Похоже, вы используете идентификаторы задач в своем коде; Я рекомендую переоценить проект, чтобы убедиться, что он может обрабатывать неуникальные идентификаторы задач. Возможно, вместо этого используется фактический экземпляр Task (который уникален).

0 голосов
/ 14 мая 2019

Вы можете сделать что-то вроде этого:

class Program
{
    static void Main(string[] args)
    {
        Guid lastID = default(Guid);
        List<CancellableTask> cancellableTasks = new List<CancellableTask>();
        for (int i = 0; i < 10; i++)
        {
            CancellableTask task = new CancellableTask(() =>
            {
                Console.WriteLine("New task!");
                Thread.Sleep(3000);
            });
            cancellableTasks.Add(task);
            lastID = task.ID;
        }

        CancellableTask cancellableTask = cancellableTasks.FirstOrDefault(x => x.ID == lastID);
        if (cancellableTask != null)
        {
            cancellableTask.Cancel();
        }
    }
}

public class CancellableTask
{
    public Guid ID { get; private set; }
    private CancellationTokenSource CancellationTokenSource { get; set; }
    public Task Task { get; private set; }
    public CancellableTask(Action action)
    {
        CancellationTokenSource = new CancellationTokenSource();
        Task = Task.Run(action, CancellationTokenSource.Token);
        ID = Guid.NewGuid();
    }
    public void Cancel()
    {
        CancellationTokenSource.Cancel();
    }
}
...