c#异步任务取消

Nor*_*gul 0 c# multithreading asynchronous task cancellationtokensource

我在掌握任务和取消令牌方面遇到了一些问题.我做了一个看起来像这样的程序:

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");

}
Run Code Online (Sandbox Code Playgroud)

我同时运行5个任务(虽然我不包括Thread.Sleep()for循环似乎运行之前,任务甚至开始?).运行程序时,没有任何任务被取消.还有什么让我烦恼的是......我在打电话时取消了什么token.Cancel()?如何选择杀死5项任务中的哪一项?我可以通过它的变量来定义每个任务,但是CancellationRequested由于它被触发,我无法访问它的属性CancellationToken.我需要5个不同的令牌吗?

Jon*_*eet 9

运行程序时,没有任何任务被取消.

那是因为你只是在任务开始时检查取消令牌.一旦它超过第一次token.IsCancellationRequested检查,取消令牌什么都不做.如果您将支票移入您的循环,如下所示:

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

...然后你会看到任务反应得当.

还有什么让我烦恼的是......我在打电话时取消了什么token.Cancel()

您没有取消任务 - 您取消了取消令牌.任何观察取消令牌的任务都将被取消(或完成,或采取任何行动),但任务和令牌之间没有直接关联.

当我们谈论"取消任务"时,我们的意思是"取消我们认为任务正在观察的令牌".