PLINQ可以生成两个流吗?错误流和数据流

时间:2017-04-07 20:51:20

标签: c# csv plinq

我正在使用PLINQ处理大型(700MB +)CSV文件。这是查询:

var q = from r in ReadRow(src).AsParallel()
    where BoolParser.Parse(r[vacancyIdx])
    select r[apnIdx];

如果您想知道,它会为空置属性生成一个APN列表。

我的问题是,如何在不对查询/流进行2次传递的情况下提取“错误记录”流?

CSV文件中的每一行都应包含colCount记录。我想通过将where子句更改为“where r.Count == colCount&& BoolParser.Parse(r [vacancyIdx])”来强制执行此操作。

但是,任何格式错误的输入都会无声地消失。

我需要捕获错误日志中的任何格式错误的行,并标记未处理n行输入。

目前我在ReadRow()函数中完成了这项工作,但似乎应该有一种将数据流拆分为2个或更多个要处理的流的方法。

那里的任何人都知道怎么做?如果没有,是否有人知道如何将此建议添加到PLINQ新功能请求中? ; - )

1 个答案:

答案 0 :(得分:0)

你要求的东西没有多大意义,因为PLINQ是基于"拉"模型(即消费者决定何时消费物品)。考虑类似的代码(为简洁起见使用C#7元组语法):

var (good, bad) = ReadRow(src).AsParallel().Split(r => r.Count == colCount);

foreach (var item in bad)
{
    // do something
}

foreach (var item in good)
{
    // do something else
}

Split的实施有两个选择:

  1. 当前项目属于另一个流时阻止一个流。

    在上面的示例中,只要出现第一个好项目,就会导致死锁。

  2. 在读取另一个流时缓存一个流的值。

    在上面的示例中,假设绝大多数项都是好的,这将导致大约700 MB的数据在两个foreach循环之间保留在内存中。所以这也是不可取的。

  3. 所以,我认为你在ReadRow中做到这一点的解决方案是可以的。

    另一种选择是:

    where CheckCount(r) && BoolParser.Parse(r[vacancyIdx])
    

    此处,CheckCount方法会报告找到的任何错误,并为其返回false。 (如果这样做,请确保使报告线程安全。)

    如果你仍然想建议向PLINQ添加这样的内容,或者只是讨论选项,你可以在the corefx repository中创建一个问题。