Как правильно отменить несколько задач в C # - PullRequest
21 голосов
/ 17 сентября 2011

У меня есть кнопка, которая порождает 4 задачи.Эта же кнопка изменится на кнопку отмены, и нажатие этой кнопки должно отменить все 4 задачи.Должен ли я передать один и тот же токен отмены всем 4 задачам и сделать так, чтобы они опрашивали одинаковый токен для IsCancelRequested?Я запутался после прочтения документа MSDN на createlinkedtokensource .Как это обычно делается?спасибо

Обновление: Task.WaitAll () ожидает выполнения все задачи завершены .Точно так же, как узнать, когда все задачи были отменены после того, как общий токен источника отмены настроен на отмену.

Ответы [ 4 ]

25 голосов
/ 17 сентября 2011

Да, то, что вы сказали об использовании одного CancellationToken, правильно.Вы можете создать один CancellationTokenSource и использовать его CancellationToken для всех задач.Ваши задачи должны регулярно проверять токен на предмет отмены.

Например:

const int NUM_TASKS = 4;

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;

Task[] tasks = new Task[NUM_TASKS];
for (int i = 0; i < NUM_TASKS; i++)
{
    tasks[i] = Task.Factory.StartNew(() =>
    {
        while (true)
        {
            Thread.Sleep(1000);
            if (ct.IsCancellationRequested)
                break;
        }
    }, ct);
}

Task.WaitAll(tasks);

Ваша кнопка может вызвать cts.Cancel();, чтобы отменить задачи.для обновления вопроса:

Есть несколько способов сделать то, что вы просите.Один из способов - использовать ct.IsCancellationRequested для проверки отмены без броска, а затем разрешить задачу.Затем Task.WaitAll(tasks) завершится, когда все задачи будут отменены.

Я обновил код, чтобы отразить это изменение.

1 голос
/ 17 сентября 2011

Да, вы должны передать тот же токен и использовать его для отмены всех задач за один раз, если это ваше намерение.

0 голосов
/ 12 июня 2018
const int NUM_TASKS = 4;

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;

Task[] tasks = new Task[NUM_TASKS];
for (int i = 0; i < NUM_TASKS; i++)
{
    tasks[i] = Task.Factory.StartNew(() =>
    {
        while (true)
        {
            Thread.Sleep(1000);
            if (ct.IsCancellationRequested)
                break;
        }
    }, ct);
}

Task.WaitAll(tasks);
0 голосов
/ 17 сентября 2011

Использование BackroundWorker класс, установка свойства WorkerSupportsCancellation , запуск задач с помощью вызова RunWorkerAsync () и остановка их с помощью CancelAsync ()

Вы не хотите синхронизировать свой код с пользовательским интерфейсом.

...