如何使用Parallel.ForEach读取csv文件头的列?

时间:2019-06-06 23:18:08

标签: c#

我必须阅读一个巨大的csv文件,并想使用Parallel.ForEach来加快阅读速度。但是,当我调试它时,列的标识不正确。有正确的方法吗?

StreamReader _headerReader = new StreamReader(folder);

string[] header = _headerReader.ReadLine().Split(',');

int headerColumn = 0;
int firstColumn = 0;
int secondColumn = 0;
int thirdColumn = 0;

// And etc...


Parallel.ForEach(header, content =>
{
    switch(header[headerColumn])
    {
    case"First"
        firstColumn = headerColumn;
        break;

    case"Second"
        SecondColumn = headerColumn;
        break;

    case"Thrid"
        thirdColumn = headerColumn;
        break;

    // And etc...

    }
    headerColumn++;
}

我想将每个列的编号放在每个列变量中,但是编号永远不会以正确的顺序出现。

1 个答案:

答案 0 :(得分:0)

您要让{this.state.recipe.tools && this.state.recipe.tools.map(tool => { return <ToolPill key={tool._id} name={tool.name} ... /> })} 处理多个线程中的字符串数组,然后忽略Parallel参数以将自己的索引滚动到该数组,而无权控制何时更改循环变量

想象一下,有两个线程正在运行您的代码,并且这些线程不同步。让我们看看会发生什么...

content

第7行,在Thread2测试了值之后,但在将值分配给 Thread1 Thread2 headerColumn 1 switch (header[headerColumn]) 0 2 case "first": 0 3 firstColumn = headerColumn; 0 4 switch (header[headerColumn]) 0 5 break; 0 6 case "first": 0 7 headerColumn++; 1 8 firstColumn = headerColumn; 1 9 break; 1 10 headerColumn++; 2 之前,Thread1递增headerColumn。因此,两个线程都为firstColumn分配了一个值,两个线程都根本没有修改firstColumn,依此类推。

这是一个极大的过度简化。实际上,多个线程可以在不同的CPU内核上同时执行。如果增量操作是通过一系列指令(例如,secondColumn)而不是原子或互锁的增量实现的,那么如果多个线程在增量过程中发生冲突,则最终load;increment;store会比预期的要少。

相反,您应该在并行部分之外生成索引,并将其与标头名称一起传入。像这样:

headerColumn

这就是说,除非您正在处理数百个列,否则您不会看到很大的速度提高……而针对数百个列编写此代码将太可怕了。

有很多优秀的CSV阅读器。例如CsvHelper,它具有CSV和类之间的自动映射,因此您不必自己处理标头,只需读取一系列对象即可。

重新发明轮子可能很有趣,您当然可以学到很多东西,但是有很多话要说,就是不要在其他人已经提供解决方案的事情上浪费时间。