C#异步任务取消

c# async task cancellation

我在掌握任务和取消标记时遇到了一些问题。我制作了一个如下所示的程序:

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 个任务(尽管当我不包括 Thread.Sleep() 时,for 循环似乎 运行 在任务开始之前?) .当我 运行 程序时,None 的任务被取消了。另外让我烦恼的是...调用 token.Cancel() 时我真正取消了什么任务?我如何选择要杀死 5 个任务中的哪一个?我可以通过它的变量定义每个任务,但我无法访问它的 CancellationRequested 属性,因为它是由 CancellationToken 触发的。那我需要 5 个不同的代币吗?

None of the tasks get ever cancelled when I run the program.

那是因为您只在任务的开始 时才检查取消标记。一旦通过了第一个 token.IsCancellationRequested 检查,取消令牌将不会执行任何操作。如果您将支票移动到循环中,如下所示:

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

...然后您会看到任务做出适当的反应。

Also what is bugging me is...what task am I really cancelling when calling token.Cancel()?

您不是在取消任务 - 您是在取消取消标记。 观察到取消令牌的任何任务都将被取消(或完成,或采取任何行动)但任务和令牌之间没有直接关联。

当我们谈论 "cancelling a task" 时,我们实际上是指 "cancelling a token which we believe the task is observing"。