C# 条件阻塞IEnumerable产生返回结果

C# 条件阻塞IEnumerable产生返回结果,c#,multithreading,ienumerable,yield-return,C#,Multithreading,Ienumerable,Yield Return,我希望有人能帮我找到一个更有效的解决我下面的问题的方法。我在多线程管道中使用IEnumerable收益率返回模式。在大多数情况下,这非常有效,但是,我有一些场景需要管道中的操作同步进行,而不是在并行线程中进行,以获得正确的结果。i、 e.遇到并发问题 现行守则如下: public override IEnumerable<Row> Execute(IEnumerable<Row> rows) { foreach (Row row in rows) {

我希望有人能帮我找到一个更有效的解决我下面的问题的方法。我在多线程管道中使用IEnumerable收益率返回模式。在大多数情况下,这非常有效,但是,我有一些场景需要管道中的操作同步进行,而不是在并行线程中进行,以获得正确的结果。i、 e.遇到并发问题

现行守则如下:

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的副本创建到列表中以强制刷新整个管道似乎效率低下。有更好的方法吗?

一般来说,阻塞执行在一定程度上是低效的。但我可能会使用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;
    }
 }

但是,是的,阻塞版本将需要对同一列表进行多次迭代,仍然需要一次来创建数组,一次来读取数组。我不确定是否有任何方法可以避免这种情况,因为您需要某种方法将其全部加载到内存中。

本质上,您想要的是枚举给定的可枚举行,假定这些行延迟返回结果,在这里被称为非阻塞,或者您想要枚举具体化的可枚举行,如rows.ToList。因此,您应该能够使用.NETFramework中已经可用的内容。SouthNote:通过收益返回创建的枚举数不是线程安全的,考虑适当的锁定,或者类似于我不理解您的问题。您说存在并发问题。但是您包含的代码中没有任何内容可以解决并发性问题。存在哪些并发问题?它们与集合的枚举有何关系?具体化集合与解决并发问题有什么关系?嗨@peter duniho,关于这个场景的完整框架,请查看开源Rhino ETL项目:场景如下。ETL管道中有几个DBCommand操作链接在一起。第一个执行插入操作,第二个执行插入行之间的匹配。匹配操作要求插入所有行以获得正确的结果。使用延迟执行会丢失一些匹配项,但强制立即加载insert DBCommand来处理所有行可以确保匹配项是正确的。@安德鲁:没有人想看到完整的框架。见和。你应该发布一个简短的问题,但仍然完全概括了你遇到的任何问题的本质。您最近的评论中没有任何内容解释集合的物化如何解决任何并发问题,尽管它确实表明您可能只是简单地调整了执行配置文件,使其不太可能发生。这只不过是简单地在枚举上进行迭代,我假设它会这样做,至少我是这样解释的//做一些工作。。。。评论。@svick天哪,说得好。我完全忽略了这一点。我已经确定了我的答案。谢谢你指出这一点。