C# 如何减少Parallel.ForEach函数的执行时间?

C# 如何减少Parallel.ForEach函数的执行时间?,c#,.net,performance,parallel.foreach,C#,.net,Performance,Parallel.foreach,代码: Factory.BuildLinkItem定义: Parallel.ForEach( infoMap, map => { var workItem = map.WorkItem; var parentInViews = viewMaps; var workbenchItem = map.WorkbenchItem; string LinkType = string.Empty;

代码:

Factory.BuildLinkItem
定义:

Parallel.ForEach(
    infoMap,
    map =>
    {
        var workItem = map.WorkItem;
        var parentInViews = viewMaps;
        var workbenchItem = map.WorkbenchItem;
        string LinkType = string.Empty;

        WorkItemLinkCollection linkedWorkItems = workItem.WorkItemLinkHistory;
        if (linkedWorkItems != null && linkedWorkItems.Count > 0)
            LinkType = linkedWorkItems[0].LinkTypeEnd.LinkType.ReferenceName;
        else if (workItem != null)
            LinkType = workItem.Store.WorkItemLinkTypes.LinkTypeEnds["Parent"].LinkType.ReferenceName;

        if (!string.IsNullOrEmpty(LinkType))
        {
            var viewMap = parentInViews.FirstOrDefault();
            if (viewMap != null)
            {
                var linkName =  LinkType;
                var childType = viewMap.ChildType;

                ILinkItem itm = Factory.BuildLinkItem(linkName, workbenchItem, workbenchItem);
                lock (Addparents)
                {
                    Addparents.Add(itm);
                }
            }
        }
    });
总共有658项,执行上述并行功能大约需要10秒

是否可以减少执行时间?如果可以,请向我建议解决方案。谢谢


注意:除了
Parallel.ForEach
,如果有任何替代方法可以提高性能并减少执行时间,请建议。谢谢。

您的问题在
lock
语句中。与其他同步机制相比,它背后的
互斥
机制的性能非常昂贵。我敢打赌,在这10秒钟中,99.99%的时间,代码都花在了关键部分的锁定和等待上。即使是非并行选择也要快得多

你有两个选择。首先是使用
.aspallel()
.Select()
.Where()
而不是
并行。ForEach
并添加到锁内的集合中。我强烈推荐这个。这样,不同项目上的操作之间的同步将自动处理

第二种选择是使用.NET4中存在的某种类型的锁,而不是锁定和正常收集。这些集合经过特别优化,可以快速添加项目,这是线程安全的

这是一个小技巧,你怎么能把它简单地转换成
aspallel

public static ILinkItem BuildLinkItem(string linkName, IWorkbenchItem parent, IWorkbenchItem child)
{         
       return new LinkItem { LinkName = linkName ?? string.Empty, Child = child, Parent = parent };
}

你试过分析你的代码并查看时间花在哪里了吗?因为我没有安装权限,所以我没有分析代码。你为什么要做
Addparents.Add(itm)
?为什么不使用
.ToList()
进行并行选择以将项目放入列表中?@Enigmativity我想是因为编写这种代码比将多个select()和Where()组合在一起以及所有这些状态要简单得多。@Enigmativity,如何更改
Addparents.Add(itm)
使用.ToList()并行选择
。谢谢。你能更新我的代码并相应地更改它吗?你的第一个选择是使用.aspallel().Select()和.Where()
。谢谢。@Euphoric-你怎么能不确定它是否有效。要么有效,要么无效。如果不行,有什么不对的?有什么错误?@Euphoric,我尝试了
.aspallel().Select()和.Where()
方法,效果很好。但是,与
Parallel.ForEach
方法相比,在多次使用中,毫秒稍高一些。我使用
System.Diagnostics.StopWatch
测试这两组代码以进行执行时间比较。最后,我将坚持使用
Parallel.ForEach
方法,与
.aspallel().Select()和.Where()
方法相比,该方法在我测试的大多数时间内执行时间更短。谢谢您的宝贵建议和解决方案。@JohnStephen您是说与您的代码相比?您确定测试正确吗?如果是这样的话,那么就有问题了,因为代码中没有任何东西表明658项需要10秒的时间。如果您使用的是实体框架,我还想到了Factory.BuildLinkItem或可能的延迟加载。@欣快,是的,我与我的代码进行了比较,我确信我的测试是正确的。此外,如果在这种情况下,
Factory.BuildLinkItem
可能是一个问题,那么我们是否可以使用任何其他解决方法来代替使用
Factory.BuildLinkItem
。谢谢以下是
Factory.BuildLinkItem
的定义<代码>公共静态ILinkItem BuildLinkItem(字符串linkName,IWorkbenchItem父项,IWorkbenchItem子项){返回新的LinkItem{linkName=linkName??string.Empty,child=child,parent=parent};}
infoMap.AsParallel().Select(
map =>
{
    var workItem = map.WorkItem;
    var parentInViews = viewMaps;
    var workbenchItem = map.WorkbenchItem;
    string LinkType = string.Empty;

    WorkItemLinkCollection linkedWorkItems = workItem.WorkItemLinkHistory;
    if (linkedWorkItems != null && linkedWorkItems.Count > 0)
        LinkType = linkedWorkItems[0].LinkTypeEnd.LinkType.ReferenceName;
    else if (workItem != null)
        LinkType = workItem.Store.WorkItemLinkTypes.LinkTypeEnds["Parent"].LinkType.ReferenceName;

    if (!string.IsNullOrEmpty(LinkType))
    {
        var viewMap = parentInViews.FirstOrDefault();
        if (viewMap != null)
        {
            var linkName =  LinkType;
            var childType = viewMap.ChildType;

            ILinkItem itm = Factory.BuildLinkItem(linkName, workbenchItem, workbenchItem);

            return new {item = itm, filter=true};
        }
    }
    return new {item = (ILinkItem)null, filter=false};
})
.Where(x=>x.filter)
.Select(x=>x.item)
.ToList();