Структурируя это как запрос LINQ, вы можете использовать метод AsParallel для выполнения его в нескольких потоках. Это значительно улучшит производительность вашего алгоритма, учитывая, что у вас так много данных.
Во-первых, нам нужно немного более структурироваться. Мы можем смоделировать значения, которые вы используете:
public class InputLine
{
public string Id { get; set; }
public string Value { get; set; }
}
public class OutputLine
{
public string Id { get; set; }
public string Value1 { get; set; }
public string Value2 { get; set; }
}
Мы также можем определить производителей и потребителей этих значений:
public class InputFile
{
private readonly string _path;
public InputFile(string path)
{
_path = path;
}
public IEnumerable<InputLine> GetLines()
{
return
from line in File.ReadAllLines(_path)
let parts = line.Split(',')
select new InputLine { Id = parts[0], Value = parts[1] };
}
}
public class OutputFile
{
private readonly string _path;
public OutputFile(string path)
{
_path = path;
}
public void WriteLines(IEnumerable<OutputLine> lines)
{
File.WriteAllLines(_path, lines.Select(line => String.Join(",", line.Id, line.Value1, line.Value2)));
}
}
Теперь у нас есть компоненты для написания запроса, который связывает все это вместе. Есть два ключевых аспекта этого запроса:
- Используйте метод расширения
.AsParallel()
, чтобы выполнить его параллельно
- Используйте оператор
join
для сопоставления клавиш между двумя входными файлами
Нам просто нужны два входных файла и выходной файл:
public void WriteResults(InputFile file1, InputFile file2, OutputFile resultFile)
{
var resultLines =
from file1Line in file1.GetLines().AsParallel()
join file2Line in file2.GetLines() on file1Line.Id equals file2Line.Id
select new OutputLine
{
Id = file1Line.Id,
Value1 = file1Line.Value,
Value2 = file2Line.Value
};
resultFile.WriteLines(resultLines);
}
Оператор join
использует аналогичный подход к словарю за кадром, и вы также получите преимущество от корреляции, выполняемой в нескольких потоках.