C# NutShell 第二十三章 任务并行

任务并行

创建并启动任务

1.指定状态对象

        static void Main(string[] args)
        {
            var task = Task.Factory.StartNew(Go,"hello");
            task.Wait();

            var task2 = Task.Factory.StartNew(state => Go(state), "world");
            Console.WriteLine(task2.AsyncState);
            task2.Wait();

            Console.WriteLine("End");
            Console.ReadLine();
        }

        static void Go(object state)
        {
            Console.WriteLine(state);
        }

2.TaskCreationOptions

可以调整任务的执行方式。

LongRunning:通知调度器为任务指定一个线程

PreferFairness:会使任务调度器的调度顺序尽可能和任务的开始顺序一致

AttachedToParent:创建子任务

3.子任务

当一个任务启动另外一个任务时,可以确定父子任务关系

父任务必须在所有子任务结束了之后才结束。而父任务结束时,子任务中的异常才向上抛出

            var task = Task.Factory.StartNew(()=>
            {
                Console.WriteLine("one");
                Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("I am a child");

                },TaskCreationOptions.AttachedToParent);
            });

等待多个任务

1.等待一个任务,可以使用Wait或者访问Result

2.或者静态方法,Task.WaitAll等待所有任务,Task.WaitAny等待任意一个任务

Task.WaitAll(task,task2);
Task.WaitAny(task, task2);

取消任务

通过在创建任务时传入取消令牌,来取消任务。取消之后,会抛出异常

            CancellationTokenSource source = new CancellationTokenSource();
            source.CancelAfter(500);
            var task = Task.Factory.StartNew(()=>
            {
                Console.WriteLine("one");
                Thread.Sleep(2000);
                
            }, source.Token);

延续任务

1.Continuewith方法将在一个任务执行完毕之后立即执行一个委托

            var task = Task.Factory.StartNew(()=>
            {
                Console.WriteLine("one");
            }).ContinueWith(ant=>
            {
                Console.WriteLine("two");
            }).ContinueWith(ant =>
            {
                Console.WriteLine("three");
            });

2.在前面的任务结束、失败、或取消后,延续的任务开始执行。参数是前面任务的引用。可以一直添加延续。

3.默认前导任务和延续会在不同的线程上执行,但是也可以设置为同一线程,需要指定选项TaskContinuationOptions.ExecuteSynchronously

4.使用前导任务的结果

            var task = Task.Factory.StartNew(()=>
            {
                Console.WriteLine("one");
                return 1;
            }).ContinueWith(ant=>
            {
                return ant.Result + 1;
            }).ContinueWith(ant =>
            {
                Console.WriteLine(ant.Result + 1);
            });

5.延续任务可以查询前导任务的Exception属性来确认前导任务是否执行失败

6.调用Wait可以重新抛出前导任务的异常

7.或者分别为异常和正常的结果指定不同的延续

8.延续任务只有在所有子任务完成之后才会执行,子任务的所有异常都会封送到延续中

9.一般延续任务是无条件运行的,但是可以通过设置来决定延续是否执行。

            var task = Task.Factory.StartNew(() =>
            {
                throw new Exception();
                Console.WriteLine("one");
            })
            .ContinueWith(ant =>
            {
                Console.WriteLine("two");
            },TaskContinuationOptions.OnlyOnRanToCompletion)
            .ContinueWith(ant =>
            {
                Console.WriteLine("three");
            });

上面的例子,one不会执行,two也不会执行,three会执行

NotOnRanToCompletion:正常执行

NotOnFaulted:在错误的时候不取消

NotOnCanceled:在取消令牌时不取消

可以用或(|)组合

10.具有多个前导任务的延续任务

WnenAll,WhenAny

            var task = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("one");
            });

            var task2 = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("two");
            });

            Task.WhenAll(task,task2).ContinueWith(ant =>
            {
                Console.WriteLine("three");
            });

并发集合

1.ConcurrentStack,ConcurrentQueue,ConcurrentBag都是用链表实现的。List没有并发集合版本。

            var d = new ConcurrentDictionary<int, int>();
            for (int i = 0; i < 20; i++)
            {
                d[i] = i;
            }

            var d1 = new Dictionary<int, int>();
            for (int i = 0; i < 20; i++)
            {
                lock (d1)
                {
                    d1[i] = i;
                }
            }

2个代码在功能上是等价的,但是在执行速度上是传统的lock语句快。读取不会有什么明显的差异。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值