ContinueWhenAll 实现线程的多重依赖

在进行多线的开发中,经常会遇到类似这样的问题

线程T4依赖T1,T2,T3的结果,T6又依赖T5和T4的结果。在有限可控的范围内,我们可以通过信号量来同步期间的关系,但是如果是在服务器或者线程数很庞大的情况下,就要三思了。

因为使用信号量意味着1,创建所有的线程并启动。2,很多线程会因为没有执行到它而阻塞。

我们知道在windows下,一个线程会耗费很多资源,其他的不说,光是内存就硬占1M。同时启很多个线程,并且其中大部分都在阻塞中,那么就意味着资源的大量浪费。

在.net 4.0中,新加入了Task类型,将任务和线程分离开了,CLR会根据算法自动生成线程,分配给task去执行。这样就很适合我们要求的这种场景。

使用ContinueWhenAll来处理这种纠结的线程间依赖关系,是再好不过的了

 

    internal class Program
    {
        private static void Main(string[] args)
        {

            var cts = new CancellationTokenSource();

            var tf = new TaskFactory<Int32>(cts.Token, TaskCreationOptions.AttachedToParent,
                                            TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

            Task<Int32> t1 = new Task<int>(() =>
                                               {



                                                   int sum = 0;

                                                   Console.WriteLine("task1 Start\n");

                                                   sum = Sum(cts.Token, 1, 2);

                                                   Console.WriteLine("task1 Done\n");

                                                   return sum;

                                               });

            Task<Int32> t2 = new Task<int>(() =>
                                               {

                                                   int sum = 0;

                                                   Console.WriteLine("task2 Start\n");

                                                   sum = Decline(cts.Token, 1, 2);

                                                   Console.WriteLine("task2 Done\n");

                                                   return sum;

                                               });

            Task<Int32> t3 = new Task<int>(() =>
                                               {

                                                   int sum = 0;

                                                   Console.WriteLine("task3 Start\n");

                                                   sum = Mulex(cts.Token, 1, 2);

                                                   Console.WriteLine("task3 Done\n");

                                                   return sum;

                                               });



            Task<Int32> t4 = tf.ContinueWhenAll(new[] {t1, t2, t3}, (compelers =>
                                                                         {

                                                                             int sum = compelers[0].Result;

                                                                             int declines = compelers[1].Result;

                                                                             int mulex = compelers[2].Result;

                                                                             Console.WriteLine("Task4 done\n");

                                                                             return sum + declines + mulex;

                                                                         }), CancellationToken.None);

            Task<Int32> t5 = new Task<int>(() =>
                                               {

                                                   int sum = 0;

                                                   Console.WriteLine("task5 Start\n");

                                                   for (int i = 0; i < 100; i++)
                                                   {

                                                       Thread.Sleep(500);

                                                       sum = 10/2;

                                                   }

                                                   Console.WriteLine("task5 Done\n");
                                                   return sum;

                                               });

            Task<Int32> t6 = tf.ContinueWhenAll(new[] {t4, t5}, compelets =>
                                                                    {

                                                                        int s1 = compelets[0].Result;

                                                                        int s2 = compelets[1].Result;

                                                                        Console.WriteLine("Task6 Done\n");

                                                                        return s1 + s2;

                                                                    }, CancellationToken.None);

            t6.ContinueWith(task =>
                                {

                                    int result = task.Result;

                                    Console.WriteLine("All Done\n Result is {0}", result);

                                });

            Thread.Sleep(200);

            t1.Start();

            t2.Start();

            t3.Start();

            t5.Start();

            Console.ReadLine();

        }

        private static int Mulex(CancellationToken token, int a1, int a2)
        {

            int result = 0;

            for (int i = 0; i < 100; i++)
            {

                result = a1*a2;

                Thread.Sleep(50);

                token.ThrowIfCancellationRequested();

            }

            return result;

        }

        private static int Decline(CancellationToken token, int a1, int a2)
        {

            int decline = 0;

            for (int i = 0; i < 100; i++)
            {

                decline = a1 - a2;

                Thread.Sleep(50);

                token.ThrowIfCancellationRequested();

            }

            return decline;

        }

        private static int Sum(CancellationToken token, int a1, int a2)
        {

            int sum = 0;

            for (int i = 0; i < 100; i++)
            {

                sum = a1 + a2;

                Thread.Sleep(50);

                token.ThrowIfCancellationRequested();

            }

            return sum;

        }
    }

  

运行结果,会先执行t1,t2,t3,t5.等t1,t2,t3执行完毕,会开始执行t4.

t4,t5运行完后会启动运行t6.

posted on 2012-10-17 23:59  suriyel  阅读(1911)  评论(0编辑  收藏  举报

导航