如何:使用分区本地变量编写 Parallel.ForEach 循环
下面的示例演示如何编写使用分区本地变量的 ForEach 方法。 当 ForEach 循环执行时,它会将其源集合划分为多个分区。 每个分区都有自己的分区本地变量的副本。 分区本地变量类似于线程本地变量,只是单个线程上可以运行多个分区。
此示例中的代码和参数非常类似于对应的 For 方法。 有关详细信息,请参阅如何:编写具有线程局部变量的 Parallel.For 循环。
若要在 ForEach 循环中使用分区本地变量,必须调用采用两个类型参数的其中一个方法重载。 第一个类型参数 TSource
指定源元素的类型,第二个类型参数 TLocal
指定分区本地变量的类型。
示例
以下示例调用 (IEnumerable
-
source
,也就是数据源。 它必须实现 “>IEnumerable<T>。 在我们的示例中,数据源是由IEnumerable<Int32>
方法返回的一百万个成员 Enumerable.Range 对象。 -
localInit
,或初始化分区本地变量的函数。 为每个在其中执行 Parallel.ForEach 操作的分区调用此函数一次。 我们的示例将分区本地变量初始化为零。 -
body
,由并行循环对循环的每个迭代调用的 “>Func<T1,T2,T3,TResult>。 其签名为Func\<TSource, ParallelLoopState, TLocal, TLocal>
。 你为委托提供代码,并且循环将传入输入参数,它们是:-
“>IEnumerable<T> 的当前元素。
-
你可以在委托的代码中用来检查循环状态的 ParallelLoopState 变量。
-
分区本地变量。
你的委托返回分区本地变量,然后将此变量传递到在该特定分区中执行的循环的下一次迭代。 每个循环分区维护此变量的一个单独实例。
在该示例中,委托将每个整数的值添加到分区本地变量,该变量维护该分区中整数元素值的不断变化着的总数。
-
-
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
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/35657.html