Reputation: 3483
I'm trying to bulk-insert a good amount of TFS-WorkItems, around 12000 Pieces, into my own Data-Model. I read them out pretty straightforward:
internal static async Task<IEnumerable<WorkItem>> GetAllWorkItemsAsync()
{
var allItems = await Task.Run(() =>
{
var result = _workItemStore.Query(@"SELECT * FROM WorkItems").Cast<WorkItem>().ToList();
return result;
});
return allItems;
}
Then I would run trough all of them in a parallel fashion and map to my own Model:
internal async Task<IEnumerable<Model.WorkItem>> GetAllWorkItemsAsync()
{
var allWorkItems = await QueryHelper.GetAllWorkItemsAsync();
var result = await Task.Factory.StartNew(() =>
{
var res = new List<Model.WorkItem>();
Parallel.ForEach(allWorkItems, wi =>
{
var item = new Model.WorkItem();
_mapper.MapCoreData(wi, item);
_mapper.MapCustomData(wi, item);
_mapper.MapLinks(wi, item);
res.Add(item);
});
return res;
}, TaskCreationOptions.LongRunning);
return result;
}
My problem: As soon, as I try to access the Work-Item Fields, for example via:
internal void MapCustomData(WorkItem source, Model.WorkItem target)
{
var sponsor = source.Fields["Sponsor"]?.Value.ToString();
var requirementType = source.Fields["Requirement Type"]?.Value.ToString();
target.WorkItemCustomData = new Model.WorkItemCustomData
{
Sponsor = sponsor,
RequirementType = requirementType,
WorkItemId = target.Id
};
}
I get the following Exception:
An exception of type 'System.InvalidOperationException' occurred in mscorlib.dll but was not handled in user code
Additional information: Collection was modified; enumeration operation may not execute.
Interesting enough, I never alter Values, but only read them and fill my own Model.
Is there any known mechanism in the TFS-Model, which has some shared Lists, or am I doing something wrong here?
Upvotes: 0
Views: 195
Reputation: 59055
What are you expecting to happen? You're working with a thread-unsafe collection within a thread:
var res = new List<Model.WorkItem>();
Parallel.ForEach(allWorkItems, wi =>
{
var item = new Model.WorkItem();
_mapper.MapCoreData(wi, item);
_mapper.MapCustomData(wi, item);
_mapper.MapLinks(wi, item);
res.Add(item);
});
return res;
Either lock around accessing the collection to provide thread safety, or use an inherently thread-safe collection like ConcurrentBag
Upvotes: 1