在进行多线的开发中,经常会遇到类似这样的问题
线程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.