所有,
我正在使用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);