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.