如何减少并行中的执行时间.ForEach函数

本文关键字:执行时间 ForEach 函数 何减少 并行 | 更新日期: 2023-09-27 17:59:13

代码:

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

Factory.BuildLinkItem定义:

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

总共存在658 items,执行上述Parallel.ForEach功能需要将近10秒

有可能减少执行时间吗?如果有,请给我一个解决方案。谢谢

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

如何减少并行中的执行时间.ForEach函数

问题出在lock语句中。与其他同步机制相比,其背后的mutex机制的性能极其昂贵。我敢打赌,在这10秒内,99.99%的代码都在关键部分锁定和等待。即使是非并行选择也会快得多。

你有两个选择。首先是使用.AsParallel().Select().Where()而不是Parallel.ForEach,并添加到锁内的集合中。我强烈推荐这个。通过这种方式,可以自动处理对不同项目的操作之间的同步。

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

这是一个小黑客,你怎么能简单地将其转换为AsParallel:

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();