Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 过滤可数模式_C#_.net_Parallel Extensions - Fatal编程技术网

C# 过滤可数模式

C# 过滤可数模式,c#,.net,parallel-extensions,C#,.net,Parallel Extensions,考虑以下简单的代码模式: foreach(Item item in itemList) { if(item.Foo) { DoStuff(item); } } 如果我想使用并行扩展(PE)将其并行化,我可以简单地替换for循环结构,如下所示: Parallel.ForEach(itemList, delegate(Item item) { if(item.Foo) { DoStuff(item); } }); 然而,对于那些Foo结

考虑以下简单的代码模式:

foreach(Item item in itemList)
{
   if(item.Foo)
   {
      DoStuff(item);
   }
}
如果我想使用并行扩展(PE)将其并行化,我可以简单地替换for循环结构,如下所示:

Parallel.ForEach(itemList, delegate(Item item)
{
   if(item.Foo)
   {
      DoStuff(item);
   }
});

然而,对于那些Foo结果为false的项目,PE将执行不必要的工作,将工作分配给线程。因此,我认为中间包装器/过滤IEnumerable可能是一种合理的方法。你同意吗?如果是这样,最简单的方法是什么?(顺便说一句,我目前正在使用C#2,所以我希望至少有一个例子不使用lambda表达式等。)

如果我要实现这一点,我只需在调用foreach之前过滤列表

var actionableResults = from x in ItemList WHERE x.Foo select x;
这将过滤列表,以获取可操作的项


注意:这可能是一个未成熟的优化,不会对您的性能产生重大影响。

所有因素都归结到这一行:

Parallel.ForEach(itemList.Where(i => i.Foo), DoStuff);
但是在阅读另一篇文章的评论时,我现在看到你已经进入了.NET2.0,所以有些问题可能有点难以通过编译器

对于.NET2.0,我认为您可以这样做(我有点不清楚作为委托传递方法名是否仍然有效,但我认为它会有效):

public IEnumerable Where(IEnumerable源,谓词)
{
foreach(源中的T项)
if(谓语(项))
收益回报项目;
}
public bool HasFoo(Item){return Item.Foo;}
Parallel.ForEach(其中(itemList,HasFoo),DoStuff);

我不确定PE for.NET 2中的分区是如何工作的,所以很难说出来。如果每个元素都被推到一个单独的工作项中(这将是一个相当糟糕的分区策略),那么预先过滤将非常有意义

然而,如果
item.Foo
恰好非常昂贵(我不希望这样,因为它是一个属性,但总是可能的),允许它并行化可能是有利的


此外,在.NET4中,TPL使用的分区策略将很好地处理这个问题。它是专门为处理不同工作水平的情况而设计的。它在“块”中进行分区,因此一个项目不会被发送到一个线程,而是一个线程被分配了一组项目,并进行批量处理。根据
item.Foo
为false的频率,并行化(使用TPL)很可能比预先过滤快。

对于记录PE,PE单独发布到.Net4,我现在正在.Net2 CLR&C#2项目中使用它。如果您愿意在C#2中使用PE的预发布端口,您应该不反对使用LINQBridge将LINQ添加到对象支持中。。。我将用
DoStuff
替换
I=>DoStuff(I)
。这是好的观点。我习惯于需要提供整个表达式语法,很容易忘记我可以为单个方法调用缩短。完成了。这让我觉得最好的计划是保持代码现在的状态,用TODO标记代码,并在我将项目升级到C#3时重新访问它。否则我会为了一点好处而得到混乱的代码。这在.NET2和C#2中是不起作用的(正如所写的那样)-扩展方法需要C#3(它在.NET2上运行,但在VS2005中不编译)…是的,忘了这一点。现在修好了。我没有从那个角度考虑过。谢谢回答得好。为了防止您对.NET 4实现感兴趣,我最近在博客中提到了TPL中的工作分区策略:
public IEnumerable<T> Where(IEnumerable<T> source, Predicate<T> predicate)
{
   foreach(T item in source)
       if (predicate(item))
          yield return item;
}

public bool HasFoo(Item item) { return item.Foo; }

Parallel.ForEach(Where(itemList, HasFoo), DoStuff);