Matthias Müller
Matthias Müller

Reputation: 3483

Parallel processing of TFS-WorkItems

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

Answers (1)

Daniel Mann
Daniel Mann

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

Related Questions