Aus*_*tin 10 .net c# parallel-processing task-parallel-library
所有,
我使用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);
});
}
Run Code Online (Sandbox Code Playgroud)
好的,所以我遇到的问题是我有28个这样的列表(一个测试样本,这应该可以扩展到200+)和FillDifferences方法非常耗时(每次调用大约4s).因此,在普通ForEach中运行的平均时间大约为100-130秒.当我在Parallel中运行相同的东西时,它需要相同的时间和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;
}
Run Code Online (Sandbox Code Playgroud)
我相信你可能会遇到线程上下文切换的代价.由于这些任务是长期运行的,我可以想象在ThreadPool上创建了许多线程来处理它们.
到4000ms只完成了第一项任务,因此这个过程将继续进行.可能的解决方案如下.
System.Threading.ThreadPool.SetMaxThreads(4, 4);
Run Code Online (Sandbox Code Playgroud)