有条件地阻止IEnumerable <t> yield返回结果</t>

时间:2014-11-11 04:35:18

标签: c# multithreading ienumerable yield-return

我希望有人可以帮我找到更有效的解决方案来解决我的问题。我在多线程管道中使用IEnumerable yield返回模式。在大多数情况下,这工作得很好,但是,我有一些情况需要管道中的操作同步发生而不是并行线程才能获得正确的结果。 (即遇到并发问题)。

现有代码是:

public override IEnumerable<Row> Execute(IEnumerable<Row> rows)
{
    foreach (Row row in rows)
    {
        //do some work....
        yield return row;
    }
}

我正在考虑创建一个可选参数来控制枚举器的阻塞输出和非阻塞输出;类似的东西:

public override IEnumerable<Row> Execute(IEnumerable<Row> rows, bool BlockingExecution)
{
    if (BlockingExecution)
    {
        return BlockingExecute(rows);
    }
    else
    {
        return NonBlockingExecute(rows);
    }
 }

 private IEnumerable<Row> NonBlockingExecute(IEnumerable<Row> rows)
 {
    foreach (Row row in rows)
    {
        //do some work....
        yield return row;
    }
 }

 private IEnumerable<Row> BlockingExecute(IEnumerable<Row> rows)
 {
     List<Row> BlockingResult = new List<Row>();
     foreach(Row r in NonBlockingExecute(rows))
     {
         BlockingResult.Add(r);
     }
     return BlockingResult;
 }

在BlockingExecute函数中,将IEnumerable的副本创建到List以强制整个管道刷新似乎效率低下。有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

一般来说,“阻止执行”会有一定程度的低效率。但我可能会使用ToArray表示该表单,并且您的非阻塞版本有点令人困惑。它真的应该为阻挡者没有做的每一个工作吗?

我可能会这样做。

public override IEnumerable<Row> Execute(IEnumerable<Row> rows, bool BlockingExecution)
{
    if (BlockingExecution)
    {
        return rows.ToArray();
    }
    else
    {
        return NonBlockingExecute(rows); // or just "return rows". It seems like the best 
                                         // practice here, in most cases anyway
                                         // would be to move that work elsewhere
    }
 }

 private IEnumerable<Row> NonBlockingExecute(IEnumerable<Row> rows)
 {
    foreach (Row row in rows)
    {
        //do some work....
        yield return row;
    }
 }

但是,是的,阻止版本将需要同一列表的多次迭代(一个用于创建数组,一个用于推测它)。我不确定有没有办法逃避这种情况,因为你想要一些方法将它全部加载到内存中。

相关问题