惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
博客园_首页
雷峰网
雷峰网
V
V2EX
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - Franky
月光博客
月光博客
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
T
Tailwind CSS Blog
小众软件
小众软件
博客园 - 叶小钗
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
Apple Machine Learning Research
Apple Machine Learning Research
IT之家
IT之家
MyScale Blog
MyScale Blog
Blog — PlanetScale
Blog — PlanetScale
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
人人都是产品经理
人人都是产品经理
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻

博客园 - Henry Cui

招聘高级.Net工程师 Node.js Web开发(二)认识Express(上) Node.js Web开发(一)从零开始 Html5 Step by Step(二) 本地存储 HTML 5 Step by Step(一) 拖放API Git学习笔记(一)初识Git DDD中的Specification模式 Silverlight 4之旅(三)数据绑定(中) Silverlight 4之旅(二)数据绑定(上) Silverlight 4之旅(一) .Net 4.0 Parallel 编程之旅 .Net 4.0 Parallel 编程(九)Task中的数据共享(下) .Net 4.0 Parallel编程(八)Task中的数据共享(中) .Net 4.0 Parallel 编程(七)Task中的数据共享(上) .Net 4.0 Parallel 编程(六)Task(下) .Net 4.0 Parallel 编程(四) Task(上) Entity Framework Code-First(下) Entity Framework Code-First(上) Entity Framework POCO T4模板使用
.Net 4.0 Parallel 编程(五)Task(中)
Henry Cui · 2010-10-28 · via 博客园 - Henry Cui

2010-10-28 22:04  Henry Cui  阅读(2645)  评论()    收藏  举报

在上篇文章中我们看过了如何创建Task,本篇文章就各种类型Task的使用进行说明。

Task Continuations

首先我们来看看延续的Task,所谓的延续的Task就是在第一个Task完成后自动启动下一个Task。我们通过ContinueWith方法来创建延续的Task。我们假设有一个接受xml解析的服务,首先从某个地方接受文件,然后解析入库,最后返回回执是否解析正确:

        [TestMethod]
        public void TaskParallelPrint()
        {
            var ReceiveTask = new Task(() => ReceiveXml());
            var ResolveTask = ReceiveTask.ContinueWith<bool>((r) => ResolveXml());
            var SendFeedBackTask = ResolveTask.ContinueWith<string>((s) => SendFeedBack(s.Result));
            ReceiveTask.Start();
            Console.WriteLine(SendFeedBackTask.Result);
        }

在每次调用ContinueWith方法时,每次会把上次Task的引用传入进来,以便检测上次Task的状态,比如我们可以使用上次Task的Result属性来获取返回值。上面的代买我们也可以这么写:

        [TestMethod]
        public void TaskParallelPrint()
        {
            var SendFeedBackTask = Task.Factory.StartNew(() => ReceiveXml())
                                    .ContinueWith<bool>(s => ResolveXml())
                                    .ContinueWith<string>(r => SendFeedBack(r.Result));
            Console.WriteLine(SendFeedBackTask.Result);
        }

Detached Nested Tasks

有些情况下我们需要创建嵌套的Task,嵌套里面又分为分离的和不分离的。其创建的方式很简单,就是在Task的body里面创建一个新的Task。如果新的Task未指定AttachedToParent选项,那么就是分离嵌套的。我们看下面这段代码:

            var outTask = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Outer task beginning...");
                var childTask = Task.Factory.StartNew(() =>
                {
                    Thread.SpinWait(3000000);
                    Console.WriteLine("Detached nested task completed.");
                });
            });
            outTask.Wait();
            Console.WriteLine("Outer task completed.");
            Console.ReadKey();

我们可以看到运行结果是:

image

上面的代码中outTask.Wait()表示等待outTask执行完成。

Child Tasks

我们将上面的代码加上TaskCreationOptions选项:

            var outTask = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Outer task beginning...");
                var childTask = Task.Factory.StartNew(() =>
                {
                    Thread.SpinWait(3000000);
                    Console.WriteLine("Detached nested task completed.");
                },TaskCreationOptions.AttachedToParent);
            });
            outTask.Wait();
            Console.WriteLine("Outer task completed.");
            Console.ReadKey();

看到运行结果:

image

Cancellation Task

如何取消一个Task呢,我们通过cancellation的tokens来取消一个Task。在很多Task的Body里面包含循环,我们可以在轮询的时候判断IsCancellationRequested属性是否为True,如果是True的话,就可以停止循环以及释放资源,同时抛出OperationCanceledException异常出来。来看一段示例代码:

            var tokenSource = new CancellationTokenSource();
            var token = tokenSource.Token;
            var task = Task.Factory.StartNew(() =>
            {
                for (var i = 0; i < 10000000; i++)
                {
                    if (token.IsCancellationRequested)
                    {
                        Console.WriteLine("Task cacel started...");
                        throw new OperationCanceledException(token);
                    }
                    
                }
            },token);
            token.Register(() =>
            {
                Console.WriteLine("Canceled");
            });
            Console.WriteLine("Press enter again to cancel task");
            Console.ReadKey();
            tokenSource.Cancel();
            try
            {
                task.Wait();
            }
            catch (AggregateException e)
            {
                foreach (var v in e.InnerExceptions)
                    Console.WriteLine("msg: " + v.Message);

            }
            Console.ReadKey();

总结

本篇文章中我们看过了创建各种不同的Task以及如何取消Task,下篇文章中会就异常处理以及Task  Laizy进行说明

alt