Parallels.ForEach以同一时间的Foreach

编程入门 行业动态 更新时间:2024-10-11 11:15:34
本文介绍了Parallels.ForEach以同一时间的Foreach的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

所有,

我现在用的是Parallels.ForEach如下:

私人无效fillEventDifferencesParallels(IProducerConsumerCollection< IEvent>事件,字典<字符串,IEvent> originalEvents)     {         Parallel.ForEach< IEvent>(事件,EVT =>         {             IEvent originalEventInfo = originalEvents [evt.EventID]             evt.FillDifferences(originalEventInfo);         });     }

好了,所以我遇到的问题是我有这28名单(测试样品,这应该是能够扩展到200+)和FillDifferences方法是相当耗费时间(大约每次通话4S) 。因此,平均时间,使之在一个正常的ForEach运行已经出现100-130s。当我并行运行同样的事情,它需要的时间是相同的和尖峰我的CPU(英特尔I5,2核心,每个核心2线程)引起的应用程序,而该查询正在运行变得缓慢(这是在一个线程中运行这是由GUI线程生成)。

我的问题是,我在做什么错,是造成这一带的时间是相同的?我读了名单是不是线程安全的,所以我重写了这个使用IProducerConsumerCollection。是否有可能会导致此任何其他陷阱?

在FillDifferences方法调用使用反射来找出有多少差异有原始的和修改后的对象之间的静态类。静态对象没有全局变量,也就是只本地被调用的方法。

有些人想看到什么叫FillDifferences()方法。这是它结束了最后:

公开名单< IDifferences> ShallowCompare(对象原稿,对象改变了,串currentName)     {         名单< IDifferences>差异=新的名单,其中,IDifferences>();         的foreach(的MemberInfo微米orig.GetType()。GetMembers())         {             名单< IDifferences> TEMP = NULL;             //遍历所有MemberInfos,直到找到一个这是一个属性。             如果(m.MemberType == MemberTypes.Property)             {                 的PropertyInfo P =(的PropertyInfo)米;                 字符串newCurrentName =;                 如果(currentName =空&安培;!&安培; currentName.Length大于0)                 {                     newCurrentName = currentName +。;                 }                 newCurrentName + = p.Name;                 反对propertyOrig = NULL;                 对象的PropertyChanged = NULL;                 //查找的原稿对象的属性信息                 如果(原稿!= NULL)                 {                     propertyOrig = p.GetValue(原稿,NULL);                 }                 //查找更改对象的属性信息                 如果(改变!= NULL)                 {                     的PropertyChanged = p.GetValue(改,空);                 }                 //发送属性,找到差异,如果有的话。这是一个浅比较。                 临时= objectComparator(P,propertyOrig,的PropertyChanged,真实,newCurrentName);             }             如果(临时=空&放大器;!&安培; temp.Count大于0)             {                 的foreach(在临时IDifferences差)                 {                     addDifferenceToList(差别,差);                 }             }         }         返回的差异;     }

解决方案

我相信您可能正在运行到线程上下文切换的成本。由于这些任务长时间运行的我能想象许多线程正在对线程池创建来处理它们。

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

通过4000ms只有第一任务已经完成所以这个过程将继续下去。一个可能的解决方案如下:

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

All,

I am using the Parallels.ForEach as follows

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

Ok, so the problem I'm having is I have a list of 28 of these (a test sample, this should be able to scale to 200+) and the FillDifferences method is quite time consuming (about 4s per call). So the Average time for this to run in a normal ForEach has been around 100-130s. When I run the same thing in Parallel, it takes the same amount of time and Spikes my CPU (Intel I5, 2 Core, 2 Threads per Core) causing the app to become sluggish while this query is running (this is running on a thread that was spawned by the GUI thread).

So my question is, what am I doing wrong that is causing this to take the same amount of time? I read that List wasn't thread safe so I rewrote this to use the IProducerConsumerCollection. Is there any other pitfalls that may be causing this?

The FillDifferences Method calls a static class that uses reflection to find out how many differences there are between the original and the modified object. The static object has no 'global' variables, just ones local to the methods being invoked.

Some of you wanted to see what the FillDifferences() method called. This is where it ends up ultimately:

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; }

解决方案

I believe you may be running into the cost of thread context switching. Since these tasks are long running I can imagine many threads are being created on the ThreadPool to handle them.

  • 0ms == 1 thread
  • 500ms == 2 threads
  • 1000 ms == 3 threads
  • 1500 ms == 4 threads
  • 2000 ms == 5 threads
  • 2500 ms == 6 threads
  • 3000 ms == 7 threads
  • 3500 ms == 8 threads
  • 4000 ms == 9 threads

By 4000ms only the first task has been completed so this process will continue. A possible solution is as follows.

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

更多推荐

Parallels.ForEach以同一时间的Foreach

本文发布于:2023-11-24 00:30:54,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1623322.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Parallels   ForEach   Foreach

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!