C#TPL锁定任务之间的共享对象,并使用Task(TResult)任务的结果填充它

时间:2012-01-06 08:57:26

标签: c# task-parallel-library

在我使用.net 4.0中的任务并行库时,我想知道从我的并行任务合并结果的最佳方法是什么,通常我需要锁定它们之间的共享对象,但现在我想知道是否Task(TResult)类并在最后合并是一个更好的解决方案?下面我考虑了两种方法:

带锁的TPL:

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;
}

TPL与最终的合并:

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;
}

是否存在正确或错误的解决方案或什么是最佳实践(非常欢迎合并并行任务结果的其他可能解决方案)

1 个答案:

答案 0 :(得分:2)

使用Parallel LINQ(它为你做了所有令人讨厌的事情),你可以把它煮成一行左右:

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