aweis
aweis

Reputation: 5596

C# TPL lock shared object between tasks vs populating it with the results from Task(TResult) tasks

In my use of the Task Parallel Library in .net 4.0 I am wondering what is the best way to merge results from my parallel tasks, normally i would require a lock on a shared object between them, but now i wondering if the Task(TResult) class and merging at the end is a better solution? Below I have the two approaches i consider:

TPL with lock:

public MyObject DoWork()
{
    var result = new MyObject();
    var resultLock = new object();
    var taskArray = new Task[this._objects.Length];
    for (var i = 0; i < taskArray.Length; i++)
    {
        taskArray[i] = new Task((obj) =>
            {
                var _o = obj as AnObject;
                var tmpResult = _o.DoTaskWork();
                lock (resultLock)
                    result.Add(tmpResult);
            }, this._objects[i]);
    }
    Task.WaitAll(taskArray);
    return result;
}

And TPL with the merging at the end:

public MyObject DoWork()
{
    var taskArray = new Task<String>[this._objects.Length];
    for (var i = 0; i < taskArray.Length; i++)
    {
        taskArray[i] = new Task<String>((obj) =>
        {
            var _o = obj as AnObject;
            return _o.DoTaskWork();
        }, this._objects[i]);
    }
    Task<String>.WaitAll(taskArray);
    var result = new MyObject();
    for (var i = 0; i < taskArray.Length; i++)
        result.Add(taskArray[i].Result);
    return result;
}

Is there a right or wrong solution or what is a best practice (other possible solution to merging results from parallel tasks are most welcome)

Upvotes: 0

Views: 1866

Answers (1)

spender
spender

Reputation: 120440

using Parallel LINQ (which does all the nasty stuff for you), you could boil this down to a single line or so:

var workResults = _objects.AsParallel().Select(DoTaskWork);
foreach(var r in workResults)
{
    result.Add(r);
}

Upvotes: 2

Related Questions