我有点卡住了,因为我无法理解这一点。
所以我有一个名为CSVItem
的课程:
public class CSVItem
{
public int SortedAccountNumber { get; set; }
public DateTime Date { get; set; }
public int SNO { get; set; }
public string AccountNumber { get; set; }
public double Value { get; set; }
public int Year
{
get
{
if (Date.Month > MainWindow.fiscalMonth)
{
return Date.Year+1;
}
return Date.Year;
}
}
public int StaticCounter { get { return 1; } }
public CSVItem(string accNo, DateTime date, double value, int sNo)
{
Value = value;
Date = date;
AccountNumber = accNo;
SNO = sNo;
}
}
我读了一个CSV,然后我制作了一个包含大约500k项目的CSV类型列表。然后我尝试使用列表的默认Order By方法进行排序,并尝试从已排序的集合中返回列表。这是代码:
List<CSVItem> items = new List<CSVItem>();
// ---- some code to read csv and load into items collection
List<CSVItem> vItems = items.OrderBy(r1 => r1.AccountNumber).ThenBy(r1 => r1.Date).ToList();
就像永远地排序然后将集合转换回列表一样。好吧,我之前已经尝试过装载大约一百万条记录,而且从来没有这样的 - 没有响应 - 来自Linq Sorting,这有点让我疯狂。关于我可以找到问题的任何帮助或建议?
答案 0 :(得分:2)
您可以使用AsParallel()
。
List<CSVItem> vItems = items.AsParallel().OrderBy(r1 => r1.AccountNumber).ThenBy(r1 => r1.Date).ToList();
问题出现了,如果OrderBy()
的并行化确实存在副作用,如果它后跟ThenBy()
。
AsParallel()
何时拆分IEnumerable
?有2个可能的答案。让我们来看看给定的查询:
items.AsParallel().OrderBy(x=>x.Age).ThenBy(x=>x.Size)
选项1
项目被拆分,每个部分按年龄排序,然后按大小排序,最后合并回1个列表。显然不是我们想要的。
选项2
项目被拆分,每个部分按年龄排序,项目合并回1个列表。之后,项目再次拆分,按大小排序并合并回1个列表。这就是我们想要的。
我创建了一个小例子来检查,哪一个是真的。
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
static void Main(string[] args)
{
List<TestItem> items = new List<TestItem>();
List<TestItem> itemsNonParallel = new List<TestItem>();
items.Add(new TestItem() { Age = 1, Size = 12 });
items.Add(new TestItem() { Age = 2, Size = 1 });
items.Add(new TestItem() { Age = 5, Size = 155 });
items.Add(new TestItem() { Age = 23, Size = 42 });
items.Add(new TestItem() { Age = 7, Size = 32 });
items.Add(new TestItem() { Age = 9, Size = 22 });
items.Add(new TestItem() { Age = 34, Size = 11 });
items.Add(new TestItem() { Age = 56, Size = 142 });
items.Add(new TestItem() { Age = 300, Size = 13 });
itemsNonParallel.Add(new TestItem() { Age = 1, Size = 12 });
itemsNonParallel.Add(new TestItem() { Age = 2, Size = 1 });
itemsNonParallel.Add(new TestItem() { Age = 5, Size = 155 });
itemsNonParallel.Add(new TestItem() { Age = 23, Size = 42 });
itemsNonParallel.Add(new TestItem() { Age = 7, Size = 32 });
itemsNonParallel.Add(new TestItem() { Age = 9, Size = 22 });
itemsNonParallel.Add(new TestItem() { Age = 34, Size = 11 });
itemsNonParallel.Add(new TestItem() { Age = 56, Size = 142 });
itemsNonParallel.Add(new TestItem() { Age = 300, Size = 13 });
foreach (var item in items.AsParallel().OrderBy(x => x.Age).ThenBy(x => x.Size))
{
Console.WriteLine($"Age: {item.Age} Size: {item.Size}");
}
Console.WriteLine("---------------------------");
foreach (var item in itemsNonParallel.OrderBy(x => x.Age).ThenBy(x => x.Size))
{
Console.WriteLine($"Age: {item.Age} Size: {item.Size}");
}
Console.ReadLine();
}
}
public class TestItem
{
public int Age { get; set; }
public int Size { get; set; }
}
<强>结果强>
AsParallel()
做我们想要的。它首先处理OrderBy()
并行,合并回列表,然后转到下一个查询,在我们的例子中ThenBy()
。我多次测试这个并且总是一样的结果。