【发布时间】:2016-02-29 11:49:58
【问题描述】:
我正在使用Parallel.ForEach 循环来完成一些工作,并使用localInit 对其进行初始化,如下所示:
localInit: () => new
{
foo = new Foo(),
bars = CreateBars(),
}
根据 MSDN:
localInit,或初始化线程局部变量的函数。 该函数在每个分区调用一次 Parallel.ForEach 操作执行。我们的示例初始化 线程局部变量为零。
所以我尝试这样使用它,但我观察到循环不断地杀死并创建新任务,这导致频繁调用localInit。我的选择会适得其反,不能按预期工作。
我认为当Parallel.ForEach 会创建例如四个分区时,它会让它们保持活动状态,直到它迭代所有项目但它没有。它正在调用localFinally 和localInit 数百次,以获得一个包含几千个项目的集合。怎么样?
可以以某种方式阻止这种行为吗?我真的希望节省一些资源,但它并没有真正让我。
下面是循环的样子:
var parallelLoopResult = Parallel.ForEach
(
source: items,
parallelOptions: parallelOptions,
localInit: () => new
{
foo = new Foo(),
bars = CreateBars(),
},
body: (item, loopState, i, local) =>
{
parallelOptions.CancellationToken.ThrowIfCancellationRequested();
var results = local.bars.Select(x => ...).ToList().
....
return local;
},
localFinally: local =>
{
local.foo.Dispose();
lock (aggregateLock)
{
... process transformed bars
}
}
);
并行选项:
var parallelOptions = new ParallelOptions
{
CancellationToken = cancellationTokenSource.Token,
#if DEBUG
MaxDegreeOfParallelism = 1
//MaxDegreeOfParallelism = Environment.ProcessorCount
#else
MaxDegreeOfParallelism = Environment.ProcessorCount
#endif
};
【问题讨论】:
-
什么是
source(IEnumerable<T>或Partitioner<T>)?你的ParallelOptions是什么? -
@svick 项目只是字符串(就像数据库中的键)。 ParallelOptions 只需指定 MaxDegreeOfParallelism (Environment.ProcessorCount) 和 CancellationToken。
标签: c# multithreading parallel.foreach