Parallel
Parallel 主要提供了For 系列方法和ForEach 系列方法,并行处理所有项。两个系列的方法都有若干重载,但最常用也最易用的是这两个。并行的目的是高效处理耗时计算
一Parallel.For(int fromInclude, int toExclude, Action<int> body)
这个方法从fromInclude 开始,到toExclude 结束,循环其中的每一个数,并对其执行body 中的代码。从参数的名称可以了解,这些数,包含了fromInclude,但不包含toExclude。
这很像for(int i = fromInclude; i < toExclude; i++) { body(i) },但与之不同的是for 语句会顺序的遍历每一个数,而Parallel.For 会尽可能的同时处理这些数——它是异步的,也就意味着,它是无序的。
Parallel.ForEach<T>(IEnumerable<T>, Action<T>)
例:
var all = new [] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Parallel.ForEach(all, (i) => {
Console.Write($"{i} ");
});
Console.WriteLine();
计算处理耗时
Stopwatch watch = new Stopwatch();
watch.Start();
Parallel.For(1, 4, LongCalc);
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
递归调用的阶乘算法来模拟耗时计算
int CalcFactorial(int n)
{
return n <= 2 ? n : n * CalcFactorial(n - 1);
}
int SumFactorial(params int[] data)
{
int sum = 0;
Parallel.ForEach(data, n => {
sum += CalcFactorial(n);
});
return sum;
}
二System.Linq.ParallelQuery
IEnumerable<T>.AsParallel() 可以很容易得到ParallelQuery<T>,改用ParallelQuery<T> 来算算阶乘之和
int SumFactorial(params int[] data)
{
return (from n in data.AsParallel()
select CalcFactorial(n)).Sum();
}
很简单的样子。而且Select() 也很熟悉,它得到的是一个ParallelQuery<T>,继承自IEnumerable<T>。所以,如果需要每一个单独的结果,只要去掉Sum(),换成ToList() 或者ToArray() 就可以了,甚至直接作为一个IEnummerable<T> 来使用也是不错的选择。
拓展:
1 "原子操作(atomic operation)是不需要synchronized",这是Java多线程编程的老生常谈了。所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切[1] 换到另一个线程)。Interlocked 类
Parallel 主要提供了For 系列方法和ForEach 系列方法,并行处理所有项。两个系列的方法都有若干重载,但最常用也最易用的是这两个。并行的目的是高效处理耗时计算
一Parallel.For(int fromInclude, int toExclude, Action<int> body)
这个方法从fromInclude 开始,到toExclude 结束,循环其中的每一个数,并对其执行body 中的代码。从参数的名称可以了解,这些数,包含了fromInclude,但不包含toExclude。
这很像for(int i = fromInclude; i < toExclude; i++) { body(i) },但与之不同的是for 语句会顺序的遍历每一个数,而Parallel.For 会尽可能的同时处理这些数——它是异步的,也就意味着,它是无序的。
Parallel.ForEach<T>(IEnumerable<T>, Action<T>)
例:
var all = new [] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Parallel.ForEach(all, (i) => {
Console.Write($"{i} ");
});
Console.WriteLine();
计算处理耗时
Stopwatch watch = new Stopwatch();
watch.Start();
Parallel.For(1, 4, LongCalc);
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
递归调用的阶乘算法来模拟耗时计算
int CalcFactorial(int n)
{
return n <= 2 ? n : n * CalcFactorial(n - 1);
}
int SumFactorial(params int[] data)
{
int sum = 0;
Parallel.ForEach(data, n => {
sum += CalcFactorial(n);
});
return sum;
}
二System.Linq.ParallelQuery
IEnumerable<T>.AsParallel() 可以很容易得到ParallelQuery<T>,改用ParallelQuery<T> 来算算阶乘之和
int SumFactorial(params int[] data)
{
return (from n in data.AsParallel()
select CalcFactorial(n)).Sum();
}
很简单的样子。而且Select() 也很熟悉,它得到的是一个ParallelQuery<T>,继承自IEnumerable<T>。所以,如果需要每一个单独的结果,只要去掉Sum(),换成ToList() 或者ToArray() 就可以了,甚至直接作为一个IEnummerable<T> 来使用也是不错的选择。
拓展:
1 "原子操作(atomic operation)是不需要synchronized",这是Java多线程编程的老生常谈了。所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切[1] 换到另一个线程)。Interlocked 类