Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 C中的Parallel.foreach#_C# 4.0 - Fatal编程技术网

C# 4.0 C中的Parallel.foreach#

C# 4.0 C中的Parallel.foreach#,c#-4.0,C# 4.0,我有一个关于并行的问题。C#中的Foreach。我是多线程新手,从上个月开始学习它。我使用一个Foreach循环,在这个Foreach循环中,我找到一个整数列表的平均值,并将每个平均值加到当前包中。但我面临的一个问题是,并不是所有迭代的结果都在增加。我的列表有10个条目,但我要添加到的当前包在foreach循环结束时只有不到10个条目。谁能告诉我我做错了什么 以下是我的代码: static void Main(string[] args) { List&l

我有一个关于并行的问题。C#中的Foreach。我是多线程新手,从上个月开始学习它。我使用一个Foreach循环,在这个Foreach循环中,我找到一个整数列表的平均值,并将每个平均值加到当前包中。但我面临的一个问题是,并不是所有迭代的结果都在增加。我的列表有10个条目,但我要添加到的当前包在foreach循环结束时只有不到10个条目。谁能告诉我我做错了什么

以下是我的代码:

static void Main(string[] args)
        {
            List<List<int>> intList = new List<List<int>>();
            List<int> ints = new List<int>();
            Random rand = new Random();
            for (int k = 1; k <= 10; k ++)
            {
                ints.Clear();
                for (int i = 0; i < 10000000; i++)
                {
                    ints.Add(rand.Next(10000000));
                }
                List<int> copy = new List<int>(ints);
                intList.Add(copy);
            }
            ConcurrentBag<double> results = new ConcurrentBag<double>();
            Parallel.ForEach<List<int>, double>(intList,
                () => 0,
                (eachIterationList, pls, threadLocal) =>
                {
                    threadLocal = eachIterationList.Average();
                    return threadLocal;
                },
                    (result) =>
                    {
                        lock (results)
                        {
                            results.Add(result);
                        }
                    });
            Console.WriteLine("No of results in results variable: {0}", results.Count);
            Console.ReadLine();
        }
static void Main(字符串[]args)
{
List intList=新列表();
List ints=新列表();
Random rand=新的Random();
对于(int k=1;k 0,
(每个操作列表,请参见threadLocal)=>
{
threadLocal=eachIterationList.Average();
返回本地;
},
(结果)=>
{
锁定(结果)
{
结果。添加(结果);
}
});
WriteLine(“results变量中的结果数:{0}”,results.Count);
Console.ReadLine();
}

当写入控制台时,results变量包含的元素少于十个,而我认为它应该包含的十个元素。

为什么要锁定results ConcurrentBag?这样做很简单:

        Parallel.ForEach(intList,
            list =>
            {
                results.Add(list.Average());
            });
锁定结果并不能保证项目的顺序正确。 如果希望两者都同步,请改用此选项:

List<double> results = new List<double>(Enumerable.Repeat(0.0d, intList.Count));
Parallel.For(0, intList.Count,
(i) =>
{
   results[i] = intList[i].Average();
});
List results=新列表(可枚举。重复(0.0d,intList.Count));
Parallel.For(0,intList.Count,
(i) =>
{
结果[i]=intList[i].Average();
});
或者使用.ForEach():

List results=新列表(可枚举。重复(0.0d,intList.Count));
Parallel.ForEach(intList,
(项目,循环,i)=>
{
结果[(int)i]=item.Average();
});

您可以看到,local finally委托在用于处理
Parallel.ForEach
的每个任务的最终操作上运行。每次都可以是不同的数字。因此,如果您修改下面列出的代码,您将看到列表迭代使用的任务数与运行最终操作的任务数相同。此终结委托的用途与您在案例中需要的用途不同

您需要了解.NET中线程和任务之间的区别。 另外,当您使用lock添加到ConcurrentBag时,您的代码也是错误的,因为它已经支持多线程添加到集合,并且您不需要锁定

 List<List<int>> intList = new List<List<int>>();
        List<int> ints = new List<int>();
        Random rand = new Random();
        for (int k = 1; k <= 10; k++)
        {
            ints.Clear();
            for (int i = 0; i < 10000000; i++)
            {
                ints.Add(rand.Next(10000000));
            }
            List<int> copy = new List<int>(ints);
            intList.Add(copy);
        }
        HashSet<int?> resultTaskIds = new HashSet<int?>();
        HashSet<int?> iterationTaskIds = new HashSet<int?>();
        ConcurrentBag<double> results = new ConcurrentBag<double>();
        Parallel.ForEach<List<int>, double>(intList,
            () => 0,
            (eachIterationList, pls, threadLocal) =>
            {
                iterationTaskIds.Add(Task.CurrentId);

                return eachIterationList.Average();
            },
                (result) =>
                {
                    resultTaskIds.Add(Task.CurrentId);
                    results.Add(result);
                });
List intList=new List();
List ints=新列表();
Random rand=新的Random();
对于(int k=1;k 0,
(每个操作列表,请参见threadLocal)=>
{
iterationTaskIds.Add(Task.CurrentId);
返回eachIterationList.Average();
},
(结果)=>
{
resultTaskIds.Add(Task.CurrentId);
结果。添加(结果);
});

谢谢Arnaud的回答。但是我想以我试图达到的方式来实现它,我知道锁定这个包是没有必要的,我曾经尝试过不锁定它,但那也不起作用,所以我选择了锁定。但是,不管怎样,我所做的有什么不对?我正在学习“Parallel.ForEach”这个特殊重载的用法,所以正在尝试它。是的,使用您的其他解决方案也可以实现这一点,但我真的想知道我所做的有什么错。不是每个项目调用一次“localFinally”,而是每个用于计算Parallel.ForEach任务的线程调用一次。更多信息请点击这里:或点击这里:谢谢!我弄错了。谢谢你安德的清楚解释,我弄错了。是的,锁定concurrentBag是没有必要的,但我尝试过不锁定,但很明显它不起作用,所以尝试了锁定,但显然不起作用,因为原因完全是其他原因。
 List<List<int>> intList = new List<List<int>>();
        List<int> ints = new List<int>();
        Random rand = new Random();
        for (int k = 1; k <= 10; k++)
        {
            ints.Clear();
            for (int i = 0; i < 10000000; i++)
            {
                ints.Add(rand.Next(10000000));
            }
            List<int> copy = new List<int>(ints);
            intList.Add(copy);
        }
        HashSet<int?> resultTaskIds = new HashSet<int?>();
        HashSet<int?> iterationTaskIds = new HashSet<int?>();
        ConcurrentBag<double> results = new ConcurrentBag<double>();
        Parallel.ForEach<List<int>, double>(intList,
            () => 0,
            (eachIterationList, pls, threadLocal) =>
            {
                iterationTaskIds.Add(Task.CurrentId);

                return eachIterationList.Average();
            },
                (result) =>
                {
                    resultTaskIds.Add(Task.CurrentId);
                    results.Add(result);
                });