0

我有一个带有运行嵌套ParallelFor循环的方法的类。基本上我正在迭代一个对象列表,然后是一个包含在每个对象属性中的列表。

根据为内部循环中的每个对象计算的条件,我想添加到队列中。我正在使用“syncRoot”对象来尝试在添加到队列时保持并发性。

public class ParallelTest
{
    private static object syncRoot = new object();

    public void Test() {
       List<MyLog> queue = new List<MyLog>();
       ...
       Parallel.For(0, set.Count(), delegate(int i)
       {
           var obj = set[i];
           List<Connection> conns = obj.GetConnections();
           ...      
           Parallel.For(0, conns.Count(), delegate(int j)
           {    
               Connection c = conns[j];
               MyLog log = new MyLog();             
               ...                  
               if (condition)
               {                    
                   lock (syncRoot)
                   {
                       queue.Add(log);
                   }
               }
           }
       }

       Debug.WriteLine(queue.Count);
   }
}

我遇到的问题是,似乎并非我的所有对象都被添加到队列中。我正在测试一组 200 个对象并将 替换为conditiontrue所以我希望queue.Count是 200。但是,我得到了奇怪的结果......有时是 200,有时是 198 或 199。

我在这里做错了什么?如何确保每个线程都被考虑在内?

4

2 回答 2

1

这似乎是 Linq 的绝佳候选者。

假设由 表示的代码...可以封装在带有签名的方法中:

void Initialize(MyLog log, Connection conn, SomeUnknownType obj)

您的代码可以简化为以下 linq 语句:

    var logs = set  
        .AsParallel()
        .SelectMany(
            obj =>
                obj.GetConnections()
                    .Select(conn => new{obj, conn}))
        .Select(x => { 
            var o = new{x.obj, x.conn, log = new MyLog()};
            Initialize(o.log, o.conn, o.obj); //or just do work inline
            return o;
        })
        .Where(x => x.obj... && x.conn...) //someCondition

    queue = logs.ToList();

鉴于set.Count()相对较高,并行化set将确保工作在可用内核上合理分配。以后无需再次并行化。

于 2012-10-29T16:37:45.037 回答
0

您可以ConcurrentQueue<T> Class改用List<T>. 请参阅http://msdn.microsoft.com/en-us/library/dd267265.aspx

了解更多信息。

于 2012-10-29T16:27:19.617 回答