【问题标题】:Parallel.Foreach vs Foreach and Task in local variable局部变量中的 Parallel.Foreach 与 Foreach 和 Task
【发布时间】:2013-04-06 20:53:49
【问题描述】:

当我们使用foreachTasks 时,我们需要像这样使用局部变量:

List<Task> TaskPool = new List<Task>();
foreach (TargetType Item in Source)
{
  TargetType localItem = Item;
  TaskPool.Add(Task.Factory.StartNew(() => DoSomething(localItem)));
}
Task.WaitAll(TaskPool.ToArray());

但是Parallel.Foreach怎么样,我是这样使用的:

Parallel.ForEach(Source, (TargetType item) => DoSomething(item));

因此,如您所见,没有任何局部变量。但是Parallel.Foreach 是如何工作的呢?不需要引入任何局部变量吗?或者如果需要,我该如何定义?

更新

.NET 4 和 .NET 4.5 有什么区别吗?

【问题讨论】:

  • 从 C# 5 开始,实际上局部变量是不必要的,因为循环变量在语义上位于循环内部。
  • @mikez 你说的循环是什么意思?你的意思是foreachParallel.foreach?如果是?那么.NET 4 怎么样?
  • 在 C# 5 中,局部变量在 foreach 循环中是不必要的(我会说 Parallel.ForEach 是方法调用而不是循环)。在 C# 4 中是必需的。我还要注意这是编译器行为,而不是运行时行为。这是与以前的编译器版本相比的“重大”变化。见blogs.msdn.com/b/ericlippert/archive/2009/11/12/…
  • 请告诉我有什么严重的错误in my answer,以至于它被严重否决了。我真的很好奇
  • @Gennady Vanin -- 新西伯利亚我不知道为什么其他人投了反对票,但在我的情况下:第一:.Net 4.5 被标记,因为我使用 .Net 4.5 第二:两个版本都不正确他们没有错,第三:您的描述如此模棱两可,您粘贴的代码为什么要同时使用Parallel.foreach和Task和Taskpool,您遵循了哪些优势?并且在您的更新中:结果不一样。谢谢

标签: c# parallel-processing task-parallel-library


【解决方案1】:

您没有在Parallel.ForEach 中定义任何局部变量-item 只不过是一个形式参数-Parallel.ForEach 的实现代码是必须处理变量的代码,以及它们是否是本地的,被捕获或者别的什么。

无需定义与形参 Parallel.ForEach 相关的局部变量 - 您的匿名委托的调用者代码将处理该变量并将其传递给您的函数。

但是在 C#4 中,如果您捕获另一个变量,则可能需要使用局部变量,即:

void DoSomething(ItemType item, OtherType other) {
}

void YourFunction(IEnumerable<ItemType> items, IEnumerable<OtherType> others) {

    foreach (var otherItem in others) {
        var localOtherItem = otherItem;
        Parallel.ForEach(items, item => DoSomething(item, localOtherItem));
    }
}

您可以看到上面的区别:localOtherItem 取自定义匿名函数的上下文:称为闭包。而items 中的项目只是作为方法参数传递给匿名函数。

简而言之:Parallel.ForEach 中的 item 和 C# 中的 item foreach 是两个截然不同的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    相关资源
    最近更新 更多