为什么在Task.Run()方法中存在“CancelationToken”类型的第二个参数?

时间:2018-04-30 08:24:02

标签: c# .net scheduled-tasks

我尝试了解重载方法Task.Run(Func, CancellationToken)的必要性。

为什么存在CancelationToken类型的第二个参数,如果它甚至没有传递到Task.Run()方法的第一个参数中指定的函数中?在sum函数代码中,我被迫使用了一个闭包。另外,我在微软的代码示例中也看到了相同的内容(请查看上面的链接)。

这是我的代码:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ThreadsLearning {
    class Program {

        private static void Main(string[] args) {

            CancellationTokenSource tokenSrc = new CancellationTokenSource();

            Func<int, int> sum = n => {
                int result = 0;

                for (var i = 0; i <= n; i++) {
                    result += i;

                    tokenSrc.Token.ThrowIfCancellationRequested();

                    Console.WriteLine(result);
                    Thread.Sleep(200);
                }
                return result;
            };

            /* Why does exist a second parameter of CancelationToken type, if it
             * is even not passed into the function specified in the first parameter
             * of Task.Run() method?
             * I'm forced to use a closure for this in the 'sum' function code.
             */
            var task = Task.Run(() => sum(30), tokenSrc.Token);

            // I will get the seame result for CancellationToken.None:
            // var task = Task.Run(() => sum(30), CancellationToken.None);

            tokenSrc.CancelAfter(TimeSpan.FromSeconds(2));

            try {
                Console.WriteLine("Result: {0}", task.Result);
            }
            catch (AggregateException ex) {
                foreach (var item in ex.InnerExceptions) {
                    Console.WriteLine("Exception: {0}", item.Message);
                }
            }
            catch (Exception ex) {
                Console.WriteLine("Other exception (the other 'catch' block): {0}", ex.Message);
            }

            Console.WriteLine("Hit <Enter> for exit...");
            Console.ReadLine();
        }
    }
}

1 个答案:

答案 0 :(得分:3)

有两个原因:

  • 如果在调用[TestMethod] public void is_constructed_with_numeric_candidate() { // Given AnotherClass obj = new AnotherClass { CandidateMode = CandidateMode.numeric }; // When MyClass myClass = new MyClass(obj); // Then // assert myClass object state is correct for numeric candidate ... } [TestMethod] public void is_constructed_with_special_candidate() { // Given AnotherClass obj = new AnotherClass { CandidateMode = CandidateMode.special }; // When MyClass myClass = new MyClass(obj); // Then // assert myClass object state is correct for special candidate ... } 时已经请求取消,则传递Task.Run可确保您的代码永远不会运行。
  • 如果您的代码从传入的同一CancellationToken中抛出OperationCanceledException,则该任务将被标记为已取消而非失败。其他代码可能会检查任务状态并相应地更改行为。