如何知道任务是否被取消或等待期结束

How to know if a task was cancelled or the wait period is over

在特定的业务场景中,有多个任务运行并行。我正在使用 CancellationToken 来在最终用户希望时取消这些任务。 我还需要在 运行 一段时间后重新启动所有任务,比如说 3 小时。为此,我使用:

_cts.CancelAfter(TimeSpan.FromHours(3))

这很好用。但是,当 3 小时到时,任务自动取消并出来。因此,我无法分别检测这两种情况,即:取消是由于用户想要取消还是因为 3 小时到了。

我知道我们可以使用包含最后 运行 时间的 Datetime 变量并将其推送到我们的任务中。然后我们可以根据当前时间和上次的时间差运行终止任务。但我更多地关注 TPL 如何帮助解决这个问题。

当然当您取消响应用户输入时,您可以在 UI 事件处理程序中设置一个标志吗?

这不会由超时设置,因此您可以区分它们。

如果 UI 允许取消单个作业,那么您可以在每个作业上下文中将标志公开为 属性。

我觉得只用TPL是不行的。我使用 System.Timers.Timer 做了一个解决方法,这是我的例子:

 public static void DifferencingCancelAfterAndCancel()
    {
        CancellationTokenSource tokenSource = new CancellationTokenSource();
        CancellationToken token = tokenSource.Token;

        Task task = new Task(() =>
        {
            for (int i = 0; i < int.MaxValue; i++)
            {
                token.ThrowIfCancellationRequested();
                token.WaitHandle.WaitOne(1000);
                Console.WriteLine("To cancel task press 'q': " + i);
            }
        }, token);

        task.Start();

        System.Timers.Timer timer = new System.Timers.Timer(10000);
        timer.Elapsed += (sender, args) =>
        {
            if (!task.IsCanceled)
            {
                tokenSource.Cancel();
                Console.WriteLine("Task was cancelled by timer!");
            }
            else Console.WriteLine("Task has already been cancelled by user");
        };

        timer.Enabled = true;

        var k = Console.ReadLine();
        if (k == "q")
        {
            if (!task.IsCanceled)
            {
                tokenSource.Cancel();
                Console.WriteLine("Task was cancelled by user!");
            }
            else Console.WriteLine("Task has already been cancelled by timer");
        }
        Console.WriteLine("Press any key to finish");
        Console.ReadLine();
    }

您声明了一个 10 秒后计时的计时器。在那之后 Elapsed 事件 将触发 lambda 函数,您可以将您的逻辑放在那里。取消任务的另一种方法是当用户点击 'q' 时,您可以在那里放置一些其他逻辑。

希望对您有所帮助