C#如何:使用分区本地变量编写 Parallel.ForEach 循环

如何:使用分区本地变量编写 Parallel.ForEach 循环

下面的示例演示如何编写使用分区本地变量的 ForEach 方法。 当 ForEach 循环执行时,它会将其源集合划分为多个分区。 每个分区都有自己的分区本地变量的副本。 分区本地变量类似于线程本地变量,只是单个线程上可以运行多个分区。

此示例中的代码和参数非常类似于对应的 For 方法。 有关详细信息,请参阅如何:编写具有线程局部变量的 Parallel.For 循环

若要在 ForEach 循环中使用分区本地变量,必须调用采用两个类型参数的其中一个方法重载。 第一个类型参数 TSource 指定源元素的类型,第二个类型参数 TLocal 指定分区本地变量的类型。

示例

以下示例调用 Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) 重载以计算一百万个元素的数组的总和。 此重载具有四个参数:

  • source,也就是数据源。 它必须实现 IEnumerable<T>。 在我们的示例中,数据源是由 IEnumerable<Int32> 方法返回的一百万个成员 Enumerable.Range 对象。

  • localInit,或初始化分区本地变量的函数。 为每个在其中执行 Parallel.ForEach 操作的分区调用此函数一次。 我们的示例将分区本地变量初始化为零。

  • body,由并行循环对循环的每个迭代调用的 Func<T1,T2,T3,TResult>。 其签名为 Func\<TSource, ParallelLoopState, TLocal, TLocal>。 你为委托提供代码,并且循环将传入输入参数,它们是:

    你的委托返回分区本地变量,然后将此变量传递到在该特定分区中执行的循环的下一次迭代。 每个循环分区维护此变量的一个单独实例。

    在该示例中,委托将每个整数的值添加到分区本地变量,该变量维护该分区中整数元素值的不断变化着的总数。

  • localFinally,当在每个分区中的循环操作完成时,Action<TLocal> 调用的 Parallel.ForEach 委托。 Parallel.ForEach 方法将此循环分区的分区本地变量的最终值传递给 Action<TLocal> 委托,并且你提供代码,以执行合并来自此分区的结果与其他分区的结果所需的操作。 此委托可以由多个任务并行调用。 因此,该示例使用 Interlocked.Add(Int32, Int32) 方法以同步对 total 变量的访问。 由于委托类型为 Action<T>,因此不存在返回值。

C#复制

 using System;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;

 class Test
 {
     static void Main()
     {
         int[] nums = Enumerable.Range(0, 1000000).ToArray();
         long total = 0;

         // First type parameter is the type of the source elements
         // Second type parameter is the type of the thread-local variable (partition subtotal)
         Parallel.ForEach<int, long>(nums, // source collection
                                     () => 0, // method to initialize the local variable
                                     (j, loop, subtotal) => // method invoked by the loop on each iteration
                                     {
                                         subtotal += j; //modify local variable
                                         return subtotal; // value to be passed to next iteration
                                     },
             // Method to be executed when each partition has completed.
             // finalResult is the final value of subtotal for a particular partition.
                                     (finalResult) => Interlocked.Add(ref total, finalResult)
                                     );

         Console.WriteLine("The total from Parallel.ForEach is {0:N0}", total);
    }
}
// The example displays the following output:
//        The total from Parallel.ForEach is 499,999,500,000
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小耕家的喵大仙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值