我有一个类,其方法是运行嵌套的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个对象并将condition
替换为true
,所以我希望queue.Count
为200.但是,我得到了奇怪的结果......有时200,有时198或199。
我在这里做错了什么?如何确保考虑每个线程?
答案 0 :(得分: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
将确保工作在可用核心上得到合理划分。以后无需再次并行化。
答案 1 :(得分:0)
您可以使用ConcurrentQueue<T> Class
代替List<T>
。见http://msdn.microsoft.com/en-us/library/dd267265.aspx
了解更多信息。