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

推荐订阅源

人人都是产品经理
人人都是产品经理
有赞技术团队
有赞技术团队
L
LangChain Blog
C
Check Point Blog
博客园 - 【当耐特】
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
V2EX
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
GbyAI
GbyAI
美团技术团队
博客园 - 司徒正美
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
S
SegmentFault 最新的问题
A
About on SuperTechFans
Blog — PlanetScale
Blog — PlanetScale
Hugging Face - Blog
Hugging Face - Blog
博客园 - 叶小钗
腾讯CDC
B
Blog
G
Google Developers Blog
The Cloudflare Blog
P
Proofpoint News Feed

博客园 - 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