Parallels.ForEach与Foreach相同的时间

所有,

我使用Parallels.ForEach如下

private void fillEventDifferencesParallels(IProducerConsumerCollection events, Dictionary originalEvents) { Parallel.ForEach(events, evt => { IEvent originalEventInfo = originalEvents[evt.EventID]; evt.FillDifferences(originalEventInfo); }); } 

好吧,所以我遇到的问题是我有28个这样的列表(测试样本,这应该能够扩展到200+),而FillDifferences方法非常耗时(每次调用大约4s)。 因此,在普通ForEach中运行的平均时间大约为100-130秒。 当我在Parallel中运行相同的东西时,它需要相同的时间和Spikes我的CPU(Intel I5,2 Core,每个Core 2个线程)导致应用程序在此查询运行时变得迟缓(这是在一个线程上运行这是由GUI线程产生的)。

所以我的问题是,我做错了什么导致这花费相同的时间? 我读到List不是线程安全的,所以我重写了这个以使用IProducerConsumerCollection。 是否有任何其他陷阱可能导致这种情况?

FillDifferences方法调用一个静态类,该类使用reflection来找出原始对象和修改对象之间存在多少差异。 静态对象没有“全局”变量,只是调用方法的本地变量。

有些人想看看FillDifferences()方法调用了什么。 这是最终结束的地方:

  public List ShallowCompare(object orig, object changed, string currentName) { List differences = new List(); foreach (MemberInfo m in orig.GetType().GetMembers()) { List temp = null; //Go through all MemberInfos until you find one that is a Property. if (m.MemberType == MemberTypes.Property) { PropertyInfo p = (PropertyInfo)m; string newCurrentName = ""; if (currentName != null && currentName.Length > 0) { newCurrentName = currentName + "."; } newCurrentName += p.Name; object propertyOrig = null; object propertyChanged = null; //Find the property Information from the orig object if (orig != null) { propertyOrig = p.GetValue(orig, null); } //Find the property Information from the changed object if (changed != null) { propertyChanged = p.GetValue(changed, null); } //Send the property to find the differences, if any. This is a SHALLOW compare. temp = objectComparator(p, propertyOrig, propertyChanged, true, newCurrentName); } if (temp != null && temp.Count > 0) { foreach (IDifferences difference in temp) { addDifferenceToList(differences, difference); } } } return differences; } 

我相信你可能会遇到线程上下文切换的代价。 由于这些任务是长期运行的,我可以想象在ThreadPool上创建了许multithreading来处理它们。

  • 0ms == 1个线程
  • 500ms == 2个主题
  • 1000毫秒== 3个线程
  • 1500毫秒== 4个线程
  • 2000毫秒== 5个主题
  • 2500毫秒== 6个线程
  • 3000毫秒== 7个主题
  • 3500毫秒== 8个线程
  • 4000毫秒== 9个线程

到4000毫秒只完成了第一项任务,因此这个过程将继续进行。 可能的解决方案如下。

 System.Threading.ThreadPool.SetMaxThreads(4, 4); 

看看它正在做什么,你的线程没有做任何事情的唯一时间是当操作系统将它们切换出来给另一个线程时,你就可以获得能够在另一个核心上运行的成本 – 所有上下文切换。

你必须扔掉一些登录才能找到确定的,但我怀疑瓶颈是物理线程,除非你有一个你还没有发布的地方。

如果这是真的,我很想重新编写代码。 有两个线程用于查找要比较的属性,另一个用于比较它们和公共队列。 可能是另一个在列表中抛出类并整理结果的人。

可能是我的旧时批处理头。