我花了大约8个小时以上在网上寻找帮助,我找不到任何东西,这里就是这样。Parallel.ForEach循环表现得像一个串行循环
我正在使用Team Foundation Server和C#,我试图获取工作项目列表并将它们转换为一个通用对象,我们将其绑定到一个特殊的用户界面。工作项目是特定日期的任务,并且该列表大小约为30个项目,因此没有那么重要。
循环是这样的:
List<IWorkItemData> workitems = new List<IWorkItemData>();
var queryForData = Store.Query(query).Cast<WorkItem>();
if (queryForData.Count() == 0)
return workitems;
Parallel.ForEach(queryForData, (wi) =>
{
var temp = wi;
lock (workitems)
{
TFSWorkItemData tfsWorkItem = new TFSWorkItemData(temp);
workitems.Add(tfsWorkItem);
}
});
TFSWorkItemData的constuctor的内部看起来是这样的:
public TFSWorkItemData(WorkItem workItem)
{
this.workItem = workItem;
this.Fields = new Dictionary<string, IFieldData>();
// Add Fields
foreach (Field field in workItem.Fields)
{
TFSFieldData fieldData = new TFSFieldData
{
Value = field.Value,
OldValue = field.OriginalValue,
ReferenceName = field.ReferenceName,
FriendlyName = field.Name,
ValueType = field.FieldDefinition.SystemType
};
this.Fields.Add(field.ReferenceName, fieldData);
}
}
因此,需要约90秒,以执行此操作。我知道抓取30个工作项目并不需要那么长时间,所以这一定是我正在做的事,导致这个过程需要很长时间。我知道锁是一个性能问题,但是当我删除它时,我得到一个InvalidOperationException异常,说该集合已被修改。当我查看这个异常的细节时,我能找到的唯一有用的信息是该集合是一个字典。奇怪的是,它并不像我在工作项目中的字段字典被修改的那样。而且我的班级里的字典只是被添加进来的,除非我失去了一些东西,否则这不应该是罪魁祸首。
请帮我弄清楚我在字典上做错了什么。我曾尝试将平行foreach循环移至workitem.Fields集合中,但似乎无法使其工作。
编辑:阅读答案的评论以回答此问题。谢谢。
你锁定的列表。将项目添加到列表是并行任务所做的唯一事情。但是你锁定了列表。 _course_它会像串行一样行事。 –
另外,你不是指'新的TFSWorkItemData(temp)'? –
锁定列表是防止发生InvalidOperationException的唯一方法。感谢您的快速响应并指出错误。 –