CancellationToken.ThrowIfCancellationRequested()抛出意外异常

时间:2018-04-12 19:47:27

标签: c# .net multithreading task semaphore

任何人都可以帮助并确定这是我的错误还是不太可能的.Net错误?

下面的代码显示了一个Main()例程,它启动了10个任务,使用DoNothing()方法作为基础方法,SemphoreSlim允许同时运行3个任务。 然后Main()等待一段时间:

Thread.Sleep(3000);

等待之后我们取消所有任务:

cancel.Cancel();

此时我预计.ContinueWith(..)将接管:

doNothingTasks.Add(
Task.Factory.StartNew(() => doNng.DoNothing(canToken), canToken)
    .ContinueWith(_ => { Console.WriteLine(..);
        }, TaskContinuationOptions.OnlyOnCanceled)

相反,我在DoNothing()例程中的以下行获得了一个异常:

Exception User-Unhandled

这是出乎意料的。

异常时的输出是: Output at exception

任何人都可以解释???

完整代码:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace TestAsync
{
    class Program
    {
        private static readonly SemaphoreSlim Broker = new SemaphoreSlim(3);

        static void Main(string[] args)
        {
            var doNothingTasks = new List<Task>();
            using (var cancel = new CancellationTokenSource())
            {
                var canToken = cancel.Token;

                for (var i = 0; i < 10; ++i)
                {
                    var doNng = new TestCancellationToken(i);
                    doNothingTasks.Add(
                        Task.Factory.StartNew(() =>
                            doNng.DoNothing(canToken), canToken)
                        .ContinueWith(_ => { Console.WriteLine(
                            $"{DateTime.Now:HH:mm:ss.ffff}.  " +
                            $"{new string('.', 25)} {doNng.Name} " +
                            $"WAS CANCELLED {new string('.', 10)}");
                        }, TaskContinuationOptions.OnlyOnCanceled)
                );
            }

            Thread.Sleep(3000);
            cancel.Cancel();

            try
            {
                Task.WaitAll(doNothingTasks.ToArray());
            }
            catch (AggregateException ae)
            {
                var fae = ae.Flatten();
                foreach (var ex in fae.InnerExceptions)
                    Console.WriteLine($"{DateTime.Now:HH:mm:ss.ffff}.  " +
                        $"{ex.GetType().Name}: {ex.Message}");
            }

            Console.WriteLine("Done.");
            Console.ReadKey();
        }
    }

    class TestCancellationToken
    {
        private readonly Random _rnd;
        public int Name { get; }

        public TestCancellationToken(int inx)
        {
            _rnd = new Random(inx);
            Name = inx;
        }

        public void DoNothing(CancellationToken canToken)
        {
            for (var i = 0; ; ++i)
            {
                if (canToken.IsCancellationRequested)
                    canToken.ThrowIfCancellationRequested();

                Broker.Wait();
                Console.WriteLine($"{DateTime.Now:HH:mm:ss.ffff}.  " +
                    $"Test {Name} round: {i}, aquire time");
                var sleepPeriod = _rnd.Next(750) + 50;

                Thread.Sleep(sleepPeriod);
                Broker.Release();
                Console.WriteLine($"{DateTime.Now:HH:mm:ss.ffff}.  " +
                    $"Test {Name} round: {i}, release time: {sleepPeriod}");
            }
        }
    }
}

}

0 个答案:

没有答案