我正在尝试使用多线程来更快地处理结果列表。我试过为每个使用并行,但是当运行过程方法时,我没有收到正确的结果。
private IEnumerable<BulkProcessorResult> GetProccessResults(List<Foo> Foos)
{
var listOfFooLists = CreateListOfFooLists(Foos);
var bulkProcessorResults = new List<BulkProcessorResult>();
Parallel.ForEach(listOfFooLists, FooList =>
{
foreach (var Foo in FooList)
{
var processClaimResult = _processor.Process(Foo);
var bulkProcessorResult = new BulkProcessorResult()
{
ClaimStatusId = (int) processClaimResult.ClaimStatusEnum,
Property1 = Foo.Property1
};
bulkProcessorResults.Add(bulkProcessorResult);
}
});
return bulkProcessorResults;
}
如果我使用普通的每个,我得到正确的输出。如果我使用上面的代码,当状态为1且状态为3时应该有3个,我得到所有2的状态。
我真的很擅长穿线,所以任何帮助都会很棒。
答案 0 :(得分:3)
最明显的问题是你正在使用多个线程(好吧,通过调用Parallel.ForEach
可以隐藏这一点,但你应该知道它通过使用多个线程/任务实现了并行性)但是你'重新使用List<T>
,它不是一个线程安全的集合类:
只要未修改集合,
List<T>
可以同时支持多个阅读器。枚举通过集合本质上不是线程安全的过程。在枚举与一个或多个写访问争用的极少数情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。要允许多个线程访问集合以进行读写,您必须实现自己的同步
不是实现自己的同步,而是在不改变代码中的其他内容的同时,我会转而使用ConcurrentQueue<T>
:
private IEnumerable<BulkProcessorResult> GetProccessResults(List<Foo> Foos)
{
var listOfFooLists = CreateListOfFooLists(Foos);
var bulkProcessorResults = new ConcurrentQueue<BulkProcessorResult>();
Parallel.ForEach(listOfFooLists, FooList =>
{
foreach (var Foo in FooList)
{
var processClaimResult = _processor.Process(Foo);
var bulkProcessorResult = new BulkProcessorResult()
{
ClaimStatusId = (int) processClaimResult.ClaimStatusEnum,
Property1 = Foo.Property1
};
bulkProcessorResults.Enqueue(bulkProcessorResult);
}
});
return bulkProcessorResults;
}
答案 1 :(得分:1)
如何将整个事物视为Parallel Linq查询?
private IEnumerable<BulkProcessorResult> GetProccessResults(List<Foo> Foos)
{
var listOfFooLists = CreateListOfFooLists(Foos);
return listOfFooLists.AsParallel()
.SelectMany(FooList => FooList)
.Select(Foo =>
new BulProcessorResult {
ClaimStatusId = (int)_processor.Process(Foo),
Property1 = Foo.Property1
}).ToList();
}