c#中的并行循环,访问同一变量

c#中的并行循环,访问同一变量,c#,performance,parallel-processing,C#,Performance,Parallel Processing,我有一个项对象,其属性名为generator\u list(字符串的哈希集)。我有8000个对象,对于每个对象,我想看看它的generator\u list是如何与其他generator\u list相交的,然后我想将相交编号存储在list中,该列表逻辑上有8000个元素 这个过程大约需要8分钟,但并行处理只需要几分钟,但我认为并行部分做得不好,因此问题就来了。有谁能告诉我,我是否需要以及如何修改代码以利用并行循环 我的项目对象的代码是: public class Item { publ

我有一个
对象,其属性名为
generator\u list
(字符串的哈希集)。我有8000个对象,对于每个对象,我想看看它的
generator\u list
是如何与其他
generator\u list
相交的,然后我想将相交编号存储在
list
中,该列表逻辑上有8000个元素

这个过程大约需要8分钟,但并行处理只需要几分钟,但我认为并行部分做得不好,因此问题就来了。有谁能告诉我,我是否需要以及如何修改代码以利用并行循环

我的
项目
对象的代码是:

public class Item
{
    public int index { get; set; }
    public HashSet<string> generator_list = new HashSet<string>();
}

有什么建议吗?

可能是这样的

 public Dictionary<int, int> Relatedness2(IList<Item> compare, Item compare_to)
        {
            int compare_to_length = compare_to.generator_list.Count;
            var intersectionData = new Dictionary<int, int>();
            foreach (Item block in compare)
            {
                int block_length = block.generator_list.Count;
                int both = 0;
                if (compare_to_length < block_length)
                {
                    foreach (string word in compare_to.generator_list)
                    {
                        if (block.generator_list.Contains(word))
                        {
                            both = both + 1;
                        }
                    }
                }
                else
                {
                    foreach (string word in block.generator_list)
                    {
                        if (compare_to.generator_list.Contains(word))
                        {
                            both = both + 1;
                        }
                    }
                }
                intersectionData[block.index] = both;
            }
            return intersectionData;
        }

不要忘记可能的字典[i]==null

线程安全集合可能就是您要寻找的

在多线程环境中工作时,需要确保 您不能同时操作共享数据,而无需 正在同步访问

NET Framework提供了一些创建的集合类 专门用于并发环境,这是您需要的 当您使用多线程时,请使用。这些藏品是 线程安全,这意味着它们在内部使用同步来 确保多个线程可以同时访问它们 时间

来源:C#考试参考70-483中的编程,目标1.1:使用并发集合实现多线程和异步处理

以下哪些是收藏

  • BlockingCollection
  • ConcurrentBag
  • ConcurrentDictionary
  • ConcurentQueue
  • ConcurentStack

如果项目的索引是连续的且从0开始,则根本不需要项目类。只要使用一个列表,它就会为您处理索引。此解决方案在并行LINQ中查找1项与其他项之间的相交计数。然后,它在另一个并行LINQ中对集合的所有项运行它。像这样

var items = new List<HashSet<string>>
{
    new HashSet<string> {"1", "2"},
    new HashSet<string> {"2", "3"},
    new HashSet<string> {"3", "4"},
    new HashSet<string>{"1", "4"}
};


var intersects = items.AsParallel().Select(     //Outer loop to run on all items
    item => items.AsParallel().Select(          //Inner loop to calculate intersects
            item2 => item.Intersect(item2).Count())
            //This ToList will create a single List<int>
            //with the intersects for that item
            .ToList() 
        //This ToList will create the final List<List<int>>
        //that contains all intersects.
        ).ToList();
var items=新列表
{
新哈希集{“1”,“2”},
新哈希集{“2”,“3”},
新哈希集{“3”,“4”},
新哈希集{“1”,“4”}
};
var intersects=items.aspallel()。选择(//要在所有项上运行的外部循环
item=>items.aspallel()。选择(//内部循环以计算相交
item2=>item.Intersect(item2.Count())
//此列表将创建一个列表
//与该项的相交
托利斯先生()
//此列表将创建最终列表
//包含所有交叉点的。
).ToList();

运行它时会发生什么?除非您想自己实现一个并发收集对象,否则您应该考虑使用一个并发收集对象,比如这个对象。另请参见:。您好,当我实际运行它时,它工作了,我曾经在该项目的属性中存储每个项目的列表结果抱歉,我在并行代码中编辑了一行,因为我必须在粘贴到此处之前修改代码,以使其更易于阅读,并行代码行看起来一定很奇怪,因为我使用了一个变量,我在其他地方没有提到,但这只是复制和粘贴我的代码并试图清理它的结果,我现在修复了它谢谢,我会尝试这个。我唯一的问题是,对于每个项目,因为它与其他项目相交,所以我希望将每个项目的所有结果存储在一个列表中。所以它看起来像7,{23,34,0,0,45100…}这意味着项目7(基于索引,它是唯一的),有一个23与项目0的交集,34与项目1的交集,。。。等等你知道我如何修改你的代码来实现这个吗?哦,等等,我刚刚运行了代码,而且速度非常快。我将尝试确认结果,我认为你的字典确实给出了我想要的值,我只是误解了你的代码。对不起,我今年夏天才开始编程!您认为您可以更新您的答案并添加此代码吗?在评论中我似乎没能很好地理解它:(谢谢,非常感谢!Parallel.ForEach(readOnlyItems.Take(1000).ToList(),item=>{dictionary[item.index]=Relatedness2(readOnlyItems,item);});这将使您获得列表前1000项的所有交叉点谢谢,我也一定会尝试!我只有机会尝试另一个答案的代码,而且我整天都在上课,呃,但一旦我有空,我也会尝试实现它。嗨,我很好奇,
newItem
的目的是什么?我理解这些项目,我想继续试试这个,但我的代码中没有与
newItem
等效的代码?@user340897可能我误解了你的代码。我以为你想将一个项目与你的项目列表进行比较,并获得列表中每个现有项目与该新项目的相交数。不过,看起来你已经找到了答案。是的,我这么认为rt是的,当我用数据的一个子集运行它时,速度非常快,但是对于所有的数据,速度和我以前的一样快……是的,现在我更好地看到了你的代码,我有点理解了,但是你能告诉我如何更改它,以便它自动循环列表中的所有项目吗?看起来你的代码只是在这样做有一个问题?@user340897更新了答案,让我知道性能。谢谢,但由于我今年夏天才开始编程,这种信息在我脑海中飞过。哈哈。但我想我明白了重点,特别是因为其中一个答案使用了并发字典,它开始揭示整个主题。
 public Dictionary<int, int> Relatedness2(IList<Item> compare, Item compare_to)
        {
            int compare_to_length = compare_to.generator_list.Count;
            var intersectionData = new Dictionary<int, int>();
            foreach (Item block in compare)
            {
                int block_length = block.generator_list.Count;
                int both = 0;
                if (compare_to_length < block_length)
                {
                    foreach (string word in compare_to.generator_list)
                    {
                        if (block.generator_list.Contains(word))
                        {
                            both = both + 1;
                        }
                    }
                }
                else
                {
                    foreach (string word in block.generator_list)
                    {
                        if (compare_to.generator_list.Contains(word))
                        {
                            both = both + 1;
                        }
                    }
                }
                intersectionData[block.index] = both;
            }
            return intersectionData;
        }
          List<Item> items = new List<Item>(8000);
        //add to list
        var dictionary = new ConcurrentDictionary<int, Dictionary<int, int>>();//thread-safe dictionary

        var readOnlyItems = items.AsReadOnly();// if you sure you wouldn't modify collection, feel free use items directly
        Parallel.ForEach(readOnlyItems, item =>
        {
            dictionary[item.index] = Relatedness2(readOnlyItems, item);
        });
var intesectiondata = dictionary[1]//dictionary of intersection for item with index 1

var countOfintersectionItemIndex1AndItemIndex3 = dictionary[1][3]
var countOfintersectionItemIndex3AndItemIndex7 = dictionary[3][7]
var items = new List<HashSet<string>>
{
    new HashSet<string> {"1", "2"},
    new HashSet<string> {"2", "3"},
    new HashSet<string> {"3", "4"},
    new HashSet<string>{"1", "4"}
};


var intersects = items.AsParallel().Select(     //Outer loop to run on all items
    item => items.AsParallel().Select(          //Inner loop to calculate intersects
            item2 => item.Intersect(item2).Count())
            //This ToList will create a single List<int>
            //with the intersects for that item
            .ToList() 
        //This ToList will create the final List<List<int>>
        //that contains all intersects.
        ).ToList();