您的位置:首页 > 编程语言 > C#

C# Parallel之for,foreach使用(笔记)

2013-12-18 14:02 651 查看
  C# 4.0 的新特性之并行库(TPL), 是 .NET Framework 4的 System.ThreadingSystem.Threading.Tasks 命名空间中的一组公共类型和 API,基本包含以下几点:

Parallel.For - for 循环的并行运算

Parallel.ForEach - foreach 循环的并行运算

Parallel.Invoke - 并行调用多个任务

Task - 任务,基于线程池。其使我们对并行编程变得更简单,且不用关心底层是怎么实现的

PLINQ - 用于对内存中的数据做并行运算,也就是说其只支持 LINQ to Object 的并行运算

  今天先记录以下For,ForEach的基本使用,也是最常用到的。方便自己使用。

  1.如果遍历集合里面的元素,做没有关系的处理时:

    For:

public static class ParallelFor_narmal
{
// 每个之间独立,不需要交互
public static void narmal()
{
int[] arry = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Parallel.For(0,arry.Length,(i,loopstate)=>
{
Console.Out.WriteLine(arry[i]);
});
}
}


    ForEach的情况差不多,这种情况是最简单的。其实也就可以使用泛型集合的ForEach(Action(T))方法了.

  2.如果集合里面的元素处理是有关联的,比如求和,但是并发是多线程的,按照传统的集合遍历肯定是有问题的,这个时候就需要了局部变量了。

    For: 

public static long withlocalvariable()
{

// int[] nums = Enumerable.Range(0, 1000000).ToArray();
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
long total = 0;
object lockflg = new object();

// Use type parameter to make subtotal a long, not an int
// 带有局部变量的并发。
// 第一个参数是for循环的起始迭代位置
// 第二个参数是for循环的终了迭代位置
// 第三个参数是局部变量的初始化。Func(T)。 这里就是给每个线程局部变量subtotal初始化为0;
// 第四个参数就是每个线程的执行的方法体。原型为Func(int,ParallelLoopState,T,B),具有三个入力参数和一个返回值的代理。
//                其中j是运行时自动提供的迭代值,loop是用来控制循环的中断,subtotal就是局部变量,最有有一个返回值。
// 第五个参数为具有一个入力参数,没有返回值的代理Action(T),用来处理每个线程的返回的结果。因为是多线程处理,所有要注意线程安全
Parallel.For<long>(0, nums.Length, () => 0, (j, loop, subtotal) =>
{
subtotal += nums[j];
return subtotal;
},
(x) =>
{ //Interlocked.Add(ref total, x);
lock (lockflg)
{
total += x;
}

}
);

return total;
}


    ForEach:

public static class ParallelForEach_WithLocalVariable
{
public static long withlocalvariable()
{
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
long total = 0;
object lockflg = new object();

//  ForEach<int, long> 第一个参数指定源元素的类型,此处的j,第二个参数指定线程本地变量的类型,此处的subtotal
Parallel.ForEach<int, long>(nums,  // 数据源
() => 0, // subtotal初始化
(j, loop, subtotal) =>{ subtotal +=j;return subtotal;}, // 每个线程执行的方法体
(x) =>{lock (lockflg) { total += x; }});  // 处理每个结果

return total;
}
}


      这两种情况是最长使用到了,其实还有更细致的控制操作,有兴趣的可以看看 数据并行(任务并行库)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: