0

У меня есть некоторые проблемы с пониманием задач и аннулирования токенов. Я сделал программу, которая выглядит следующим образом: (? Хотя, когда я не включает Thread.Sleep() цикл for кажется скороходы задачи даже начало)C# async task cancelation

static void Main(string[] args) 
{ 

    CancellationTokenSource token = new CancellationTokenSource(); 
    Stopwatch stop = new Stopwatch(); 
    stop.Start(); 

    for (int i = 0; i < 5; i++) 
    { 
     //Thread.Sleep(1000); 
     Task.Factory.StartNew(() => myLongTask(token.Token, (i + 1) * 1000)); 
    } 
    while (true) 
    { 
     Thread.SpinWait(1000); 
     if (stop.ElapsedMilliseconds > 3000) 
     { 
      token.Cancel(); 
     } 
    } 
} 

public static void myLongTask(CancellationToken token, int time) 
{ 
    if (token.IsCancellationRequested) 
    { 
     Console.WriteLine("Cancelled"); 
     return; 
    } 
    var sw = Stopwatch.StartNew(); 
    Console.WriteLine($"Task {time/1000} started"); 
    while (sw.ElapsedMilliseconds < time) 
     Thread.SpinWait(1000); 
    Console.WriteLine($"Task {time/1000} ended"); 

} 

Я бег 5 задач одновременно. Ни одна из задач не отменяется, когда я запускаю программу. Также меня беспокоит то, что ... какую задачу я действительно отменяю при вызове token.Cancel()? Как я могу выбрать, какую из 5 задач я убью? Я могу определить каждую задачу по ее переменной, но я не могу получить доступ к ее свойству CancellationRequested, так как он запускается с CancellationToken. Должен ли мне понадобиться 5 разных токенов?

ответ

8

Ни одна из задач не отменяется, когда я запускаю программу.

Это потому, что вы только когда-либо проверки токен отмены на начать задачи. После того, как прошло уже первое очко token.IsCancellationRequested, отмена маркера ничего не делает. Если вы перемещаете свой чек в свой цикл, как это:

while (sw.ElapsedMilliseconds < time) 
{ 
    if (token.IsCancellationRequested) 
    { 
     Console.WriteLine("Cancelled"); 
     return; 
    } 
    Thread.SpinWait(1000); 
} 

... тогда вы увидите задачи реагировать соответствующим образом.

Кроме того, что меня беспокоит, какую задачу я действительно отменяю при вызове token.Cancel()?

Вы не отменяете задачу - вы отменяете токен отмены. Любая задача, которая отмечает, что токен отмены будет отменен (или закончен, или что бы это ни было сделано), но нет прямой корреляции между задачей и токеном.

Когда мы говорим об «отмене задачи», мы действительно имеем в виду «отмену токена, который, как мы считаем, выполняет наблюдение».

+0

Но если у меня есть 5 разных задач и только один 'token.Cancel()' ... то он отменяет все 5, очевидно? Если я хочу убить конкретную задачу, нужен ли мне токен? – Norgul

+0

@ Норгул: Да. Или, по крайней мере, вам понадобятся 5 разных токенов и * некоторый способ узнать, какой из них наблюдается в задаче, которую вы хотите остановить. –