2012-01-06 44 views
0

在我使用.NET 4.0任务并行库我想知道什么是合并从我的并行任务结果的最佳方式的结果填充它,通常我会要求他们之间的共享对象上的锁,但现在我想知道如果Task(TResult)类和合并的到底是一个更好的解决方案?下面我有两种方法,我认为:C#TPL锁定任务之间共享对象VS与任务(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; 
} 

有没有正确或错误的解决方案或者是什么最佳实践(其他可能的解决方案来合并来自并行任务的结果是最欢迎的),使用并行LINQ(它的所有肮脏的东西你)

回答

2

,你可以煮这个到一个单一的线路或这样:

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

您好,我真的很喜欢这个建议的解决方案,简单LINQ'ed,但如果是我会用任务库的情况下,这将是最好! – aweis 2012-01-06 09:19:27

+0

在这种情况下,我会使用并发集合中的一个(http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx),并从任务体直接添加到它。不要忘记,PLinq在引擎盖下使用TPL。 – spender 2012-01-06 09:25:18

+0

好的,ConcurrentDictionary将会非常适合。 PLINQ是如何执行的,因为我经常读到使用LINQ查询数据结构与时间相关的代价很高,PLINQ中是否存在一些向上/向下的方面,而时间成为一个非常重要的因素? – aweis 2012-01-06 09:32:23