Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 跨嵌套的并行循环同步_C#_.net 4.0_Parallel Processing - Fatal编程技术网

C# 跨嵌套的并行循环同步

C# 跨嵌套的并行循环同步,c#,.net-4.0,parallel-processing,C#,.net 4.0,Parallel Processing,我有一个类,其方法运行嵌套的ParallelFor循环。基本上,我迭代对象列表,然后是包含在每个对象属性中的列表 根据为内部循环中的每个对象计算的条件,我想添加到队列中。我使用“syncRoot”对象试图在添加到队列时保持并发性 public class ParallelTest { private static object syncRoot = new object(); public void Test() { List<MyLog> queue

我有一个类,其方法运行嵌套的
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);
   }
}
公共类并行测试
{
私有静态对象syncRoot=新对象();
公开无效测试(){
列表队列=新列表();
...
Parallel.For(0,set.Count(),委托(inti)
{
var obj=集合[i];
List conns=obj.GetConnections();
...      
Parallel.For(0,conns.Count(),委托(intj)
{    
连接c=接头[j];
MyLog log=new MyLog();
...                  
如果(条件)
{                    
锁定(同步根)
{
添加(日志);
}
}
}
}
Debug.WriteLine(queue.Count);
}
}
我的问题是,似乎并不是所有的对象都被添加到队列中。我正在测试一组200个对象,并将
条件
替换为
,因此我预计
队列.计数
为200。然而,我得到了奇怪的结果…有时是200,有时是198或199


我在这里做错了什么?我如何确保每个线程都得到解释?

您可以使用
ConcurrentQueue类
代替
列表
。请参阅


更多信息。

这似乎是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()
相对较高,在
集合上进行并行化将确保工作在可用内核上得到合理的分配。以后无需再次并行化。

这是一个相当广泛的局部变量锁定策略。如果您只需要在
队列
的相同范围内声明
syncLock
使用它。更好的是,既然不能保证排序,为什么不使用
ConcurrentBag
并完全取消锁定?尝试了
ConcurrentBag
。同样的行为。第一次测试200,第二次199。我可能会失去理智,但我收回了我以前的评论。这似乎正在起作用。我将在下一次测试中测试它地面,看看我是否可以打破它,但这可能是我需要的解决方案。如果你可以远离显式循环和显式锁定,你肯定不会太容易受到这种问题的影响。在创建每个日志后,“…”的一部分是一些处理,需要一个变量(并且可能很长)时间量,所以并行性很重要。未知。我正在使用200-300进行批量测试,认为这将是一个很高的量。但这取决于时间。@Paul希望对我的答案所做的更改符合您的需要。他们将确保额外的工作并行化。