我正在使用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新功能请求中? ; - )
答案 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
的实施有两个选择:
当前项目属于另一个流时阻止一个流。
在上面的示例中,只要出现第一个好项目,就会导致死锁。
在读取另一个流时缓存一个流的值。
在上面的示例中,假设绝大多数项都是好的,这将导致大约700 MB的数据在两个foreach
循环之间保留在内存中。所以这也是不可取的。
所以,我认为你在ReadRow
中做到这一点的解决方案是可以的。
另一种选择是:
where CheckCount(r) && BoolParser.Parse(r[vacancyIdx])
此处,CheckCount
方法会报告找到的任何错误,并为其返回false
。 (如果这样做,请确保使报告线程安全。)
如果你仍然想建议向PLINQ添加这样的内容,或者只是讨论选项,你可以在the corefx repository中创建一个问题。