Есть ли способ отменить выполнение метода в отмененной задаче? - PullRequest
1 голос
/ 17 мая 2019

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

Сейчас я не представляю, как остановить выполнение метода вместе с задачей.

Ниже приведен цикл, который выполняетсязадачи.Каждая задача выполняет метод ParseHorseData, который также запускает несколько других методов.Их выполнение иногда занимает много времени.

После отмены задания, до завершения await Task.WhenAll(tasks);, требуется много времени.

Итак, как и в вопросе,Есть ли способ отменить выполнение метода в отмененной задаче?

List<Task> tasks = new List<Task>();
int loopCounter = 0;
int taskCounter = 0;

//for all races in the file
for (int i = 0; i < _allRaces.Count; i ++)
{
    int j = i;

    if (TaskCancellation == true)
    {
        break;
    }

    Task task = Task.Run(async () =>
    {
        while (!_cancellationToken.IsCancellationRequested)
        {
            loopCounter++;

            ProgressBarTick("Requesting historic data", loopCounter, _allRaces.Count, 0);

            //if the race is from 2018
            if (_allRaces[j].RaceDate.Year == 2018)
            {
                Category = _allRaces[j].RaceCategory;
                Distance = _allRaces[j].RaceDistance.ToString();

                //for all horses in the race
                for (int h = 0; h < _allRaces[j].HorseList.Count; h++)
                {
                    HorseDataWrapper horse = new HorseDataWrapper();


                    //TIME CONSUMING
                    horse = ParseHorseData(_allRaces[j].HorseList[h], _allRaces[j].RaceDate);
                    _allRaces[j].HorseList[h] = horse;
                }
            }

            taskCounter++;

            if (loopCounter >= _allRaces.Count)
            {
                ProgressBarTick("Testing on historic data", taskCounter, _allRaces.Count, 0);
            }
        }
    }, _tokenSource.Token);

    tasks.Add(task);
}

try
{
    await Task.WhenAll(tasks);
}
catch (TaskCanceledException)
{
    //
}
finally
{
    _tokenSource.Dispose();
}

1 Ответ

3 голосов
/ 17 мая 2019

есть ли способ отменить выполнение метода в отмененной задаче?

Все отмены являются совместными. Выполняемый метод должен передать CancellationToken в методы, которые он вызывает, и либо:

  1. Периодически запрашивать отмену с помощью ThrowIfCancellationRequested. Этот подход больше подходит для циклов, связанных с процессором.
  2. Примите меры по отмене, используя Register. Этот подход больше подходит для взаимодействия с системами аннулирования, не основанными на CancellationToken.

В этом случае звучит так, что опрос подходит. Я настоятельно рекомендую опрашивать через ThrowIfCancellationRequested, а не IsCancellationRequested, потому что, когда задача отменяется, она должна выдавать OperationCanceledException, когда await ed. Вот как вызывающий код узнает, что он был отменен.

* * 1 022 Пример: * 1 023 *
Task task = Task.Run(async () =>
{
  while (true)
  {
    _cancellationToken.ThrowIfCancellationRequested();
    ...
       //for all horses in the race
       for (int h = 0; h < _allRaces[j].HorseList.Count; h++)
       {
          _cancellationToken.ThrowIfCancellationRequested();
          HorseDataWrapper horse = new HorseDataWrapper();
          horse = ParseHorseData(_allRaces[j].HorseList[h], _allRaces[j].RaceDate);
          _allRaces[j].HorseList[h] = horse;
       }
    ...
  }
});
...