1

我们得到了以下场景:

class Program
{
    static void Main(string[] args)
    {
        // trigger the delayed function
        trigger();

        // cancel the running task.
        _token.Cancel();

        // keep window open ;-)
        Console.ReadLine();

    }

    private static CancellationTokenSource _token = null;
    private static async void trigger()
    {
        _token = new CancellationTokenSource();

        try
        {
            // run task
            await Task.Run(async () =>
            {
                // wait time
                await Task.Delay(2500);

                // we should be cancelled here !!
                Console.WriteLine(string.Format("IsCancellationRequested={0}", _token.Token.IsCancellationRequested));
                Console.WriteLine("SHOULD NOT HAPPEN");

            }, _token.Token);
        }
        catch (TaskCanceledException)
        {
        }
    }
}

IMO 预期的行为是任务的操作大部分在Task.Delay(2500)被处理后被取消。

但控制台正在打印:

IsCancellationRequested=True
SHOULD NOT HAPPEN

这感觉就像一个错误。如果您将CancellationToken作为参数添加到Task.Delay -Function,它将按预期工作。

那么,如果任务中的函数使用Task.Delay,您可能不知道如何处理取消?

4

2 回答 2

3

.Net 中的取消是合作的。将令牌作为参数传递给Task.Run仅将令牌与返回的任务相关联。

要实际取消任务,您需要检查任务本身内部的令牌。如果您希望在延迟内取消任务,您需要将令牌传递给该Task.Delay方法。否则,您只能在延迟之前或之后检查:

await Task.Run(async () =>
{
    _token.Token.ThrowIfCancelltionRequested();
    await Task.Delay(2500, _token.Token);
    _token.Token.ThrowIfCancelltionRequested();

    Console.WriteLine(string.Format("IsCancellationRequested={0}", _token.Token.IsCancellationRequested));
    Console.WriteLine("SHOULD NOT HAPPEN");

}, _token.Token);
于 2015-07-10T15:21:01.920 回答
1

这是一篇不错的 MSDN 文章:https ://msdn.microsoft.com/en-us/library/dd537607(v=vs.110).aspx

调用线程不强制结束任务;它仅表示请求取消。如果任务已经在运行,则由用户委托来通知请求并做出适当的响应。如果在任务运行之前请求取消,则永远不会执行用户委托,并且任务对象将转换为 Canceled 状态。

正如 i3arnon 建议的那样,您可以在执行实际工作之前检查状态并抛出异常。文章代码摘录:

...
  // Was cancellation already requested?  
      if (ct.IsCancellationRequested == true) {
         Console.WriteLine("Task {0} was cancelled before it got started.",
                           taskNum);
         ct.ThrowIfCancellationRequested();
      } 
...
于 2015-07-10T15:25:38.367 回答