Parallels.ForEach以同一时间的Foreach [英] Parallels.ForEach Taking same Time as Foreach

查看:155
本文介绍了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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆