所有,
我正在使用Parallels.ForEach如下
private void fillEventDifferencesParallels(IProducerConsumerCollection<IEvent> events,Dictionary<string,IEvent> originalEvents) { Parallel.ForEach<IEvent>(events,evt => { IEvent originalEventInfo = originalEvents[evt.EventID]; evt.FillDifferences(originalEventInfo); }); }
好的,所以我遇到的问题是我有一个这样的28个列表(一个测试样本,这应该能够扩展到200),而FillDifferences方法是相当耗时(每次呼叫约4秒).所以在一个正常的ForEach中运行的平均时间大约是100-130秒.当我并行运行相同的事情时,它需要相同的时间和Spikes我的cpu(Intel I5,2 Core,每个Core的2个线程),导致该应用程序在此查询运行时缓慢(这是在一个线程上运行这是由GUI线程产生的).
所以我的问题是,我做错了什么导致这需要相同的时间?我看到List不是线程安全的,所以我重写了使用IProducerConsumerCollection.是否有其他可能导致这种情况的陷阱?
FillDifferences方法调用使用反射的静态类,以找出原始对象和修改对象之间有多少差异.静态对象没有“全局”变量,只是调用方法的本地变量.
你们中有些人想看看什么是FillDifferences()方法.这是最终结束的地方:
public List<IDifferences> ShallowCompare(object orig,object changed,string currentName) { List<IDifferences> differences = new List<IDifferences>(); foreach (MemberInfo m in orig.GetType().GetMembers()) { List<IDifferences> 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上创建许多线程来处理它们.
> 0ms == 1线程
> 500ms == 2线程
> 1000 ms == 3线程
> 1500 ms == 4线程
> 2000 ms == 5线程
> 2500 ms == 6线程
> 3000 ms == 7线程
> 3500 ms == 8线程
> 4000 ms == 9线程
只有4000ms,第一个任务已经完成,所以这个过程将继续.一个可能的解决方案如下.
System.Threading.ThreadPool.SetMaxThreads(4,4);