TaskFactory

作者:追风剑情 发布于:2017-10-19 11:58 分类:C#

示例

using System;
using System.Text;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace TaskTest2
{
    class Program
    {
        static void Main(string[] args)
        {
            Task parent = new Task(() =>
            {
                var cts = new CancellationTokenSource();
                // 利用任务工厂可以创建一组共享相同配置的任务
                var tf = new TaskFactory<Int32>(
                    cts.Token,
                    //用此工厂创建的所有任务都将被视为子任务
                    TaskCreationOptions.AttachedToParent,
                    //延续任务在前置任务所在的线程运行,
                    //如果前置任务已经执行完成,则在创建它的线程中运行
                    TaskContinuationOptions.ExecuteSynchronously,
                    //采用默认调度器
                    TaskScheduler.Default);

                // 这个任务创建并启动3个子任务
                var childTasks = new[]{
                    tf.StartNew(()=>Sum(cts.Token, 10000)),
                    tf.StartNew(()=>Sum(cts.Token, 20000)),
                    //tf.StartNew(()=>Sum(cts.Token, Int32.MaxValue))//太大,抛出OverflowException
                };

                // 任何子任务抛出异常,就取消其余子任务
                for (Int32 task = 0; task < childTasks.Length; task++)
                    childTasks[task].ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);

                // 所有子任务完成后,从未出错/未取消的任务获取返回的最大值
                // 然后将最大值传递给另一个任务来显示最大结果
                tf.ContinueWhenAll(
                    childTasks,
                    //必须引入System.Linq命名空间,否则会报Where未定义。
                    completedTasks => completedTasks.Where(
                        t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result),
                        //覆盖TaskFactory的CancellationToken
                        //这里传None是为了子任务被取消后,此任务依然可以执行
                        CancellationToken.None)
                        .ContinueWith(t => Console.WriteLine("The maximum is: "+t.Result),
                        TaskContinuationOptions.ExecuteSynchronously);
            });

            // 子任务完成后,也显示任何未处理的异常
            parent.ContinueWith(p =>
            {
                StringBuilder sb = new StringBuilder(
                    "The following exception(s) occurred:" + Environment.NewLine);

                foreach (var e in p.Exception.Flatten().InnerExceptions)
                    sb.AppendLine(" " + e.GetType().ToString());
                Console.WriteLine(sb.ToString());
            },
            TaskContinuationOptions.OnlyOnFaulted);

            // 启动父任务
            parent.Start();

            Console.ReadLine();
        }

        private static Int32 Sum(CancellationToken ct, Int32 n)
        {
            Int32 sum = 0;
            for (; n > 0; n--)
            {
                //在取消标志引用的CancellationTokenSource上调用Cancel,
                //下面这行代码就会抛出OperationCanceledException
                ct.ThrowIfCancellationRequested();

                //如果n太大,会抛出System.OverflowException
                checked { sum += n; }
            }
            return sum;
        }
    }
}

运行测试

111.png

标签: C#

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号