c#并行修改DataRow数组引用.为什么代码可以正确运行

本文关键字:运行 代码 为什么 修改 并行 DataRow 数组 引用 | 更新日期: 2023-09-27 18:07:36

这不是我对代码所做的,但它应该代表交换数组引用的场景。我不确定数组的类型是否重要,但我仍然在标题中指定了它。

    在循环外声明一些DataRow数组。命名为Array1, Array2…ArrayX等
  1. Array1 = Array2或Array1 = Array3…或Array1 = ArrayX取决于迭代变量
  2. 对Array1做点什么

代码应该像这样:

void Somefunction()
{
    int indices[];
    for (int i = 0; i < threadamount; ++i)
    {
        indices[i] = i;
    }
    DataRow[] Array1, Array2, Array3;
    //assign something to these arrays
    //...
    //end of assigning stuff
    Parallel.ForEach<int>(indices, index =>
    {
        if(index == 2)
           Array1 = Array2;
        else if(index == 3)
           Array1 = Array3;
        //do stuff with Array1
     });
 }

回到问题上来。似乎代码在所有数组上运行(在其他线程中正确地将Array2/Array3分配给Array1),没有竞争条件。

为什么?我以为我必须在循环中创建一个新变量,但是没有。是因为它实际上为每个线程创建了一个Array1引用的副本吗?每个线程中的引用Array1实际上是不同的对象?

PS:这是我的第一个问题,所以我希望我没有犯任何错误在我把这个贴出来之前,我确实读了一些其他的问题,但他们并没有真正回答我的问题。

c#并行修改DataRow数组引用.为什么代码可以正确运行

我想你错了,问题。

我修改了你的代码,以测试Array1是否在线程设置后发生了变化,结果发现它有时会发生变化。

如果更改了Array1,下面的代码将打印"Error!"在我的系统上,它在发布或调试版本(四核处理器)上多次打印"Error"。

每次运行的结果是不同的(这是您对竞争条件的期望):

using System;
using System.Threading.Tasks;
namespace Demo
{
    static class Program
    {
        static void Main()
        {
            Somefunction();
        }
        static void Somefunction()
        {
            int threadamount = 100;
            int[] indices = new int[threadamount];
            for (int i = 0; i < threadamount; ++i)
            {
                indices[i] = i;
            }
            int[] Array1 = new int[1],
                  Array2 = new int[2],
                  Array3 = new int[3];
            Parallel.ForEach<int>(indices, index =>
            {
                if (index == 2)
                    Array1 = Array2;
                else if (index == 3)
                    Array1 = Array3;
                int[] test = Array1;
                Console.WriteLine(Array1.Length);
                if (!ReferenceEquals(test, Array1))
                {
                    Console.WriteLine("Error!");
                }
             });
         }
    }
}