C # Parallel.Foreach int [] в списке <T>не изменен должным образом - PullRequest
0 голосов
/ 08 сентября 2018

Это мой класс:

public class UnusedRolesOccurrence
{
    public string Username { get; set; }
    public string FullName { get; set; }
    public string Role { get; set; }
    public int[] Month { get { return month; } set { month = value; } }
    private static int[] month = new int[12];
}

И здесь я хочу заполнить массив int значениями:

Parallel.ForEach(unusedrolesoccurrence, (UnusedRolesOccurrence item) =>
{
    try
    {
        lock (listLock)
        {

            int count = tmp.Count(x => x.Username == item.Username && x.Role == item.Role);
            item.Month[month] = count;

            if (count > 2)
            {
                Debug.WriteLine($"{item.Username},{item.Role},{month}={count},{item.Month[month]}");
            }
        }
    }
    catch
    {
        //
    }
});

List<unusedrolesoccurrence> предварительно заполняется данными. Месяц массив [0,0,0,0,0,0,0,0,0,0,0,0] перед началом foreach, с int[] arr_month = new int[12];.

tmp также является List<t>.

Что не работает: во время цикла число, а также значение item.Month[month] является правильным. Но не в цель List<UnusedRolesOccurrence>. Все месяцы - это одно и то же значение последнего счета, обработанного в цикле, например [3,0,3,0,0,0,0,0,0,0,0,0] или [0,1,1,0,0,0,0,0,0,0,0,0 ]. И потому, что параллельно, это всегда другой результат, конечно.

Я изменил int[] на public Dictionary<int, int> Month { get; set; } для тестирования, но такое же поведение.

ЗДЕСЬ ПРИМЕР КОДА (с // вторичной попыткой со словарем с тем же результатом):

public class UnusedRoles
        {
            public string Username { get; set; }
            public string Role { get; set; }
            public int Month { get; set; }
        }

        public class UnusedRolesOccurrence
        {
            public string Username { get; set; }
            public string Role { get; set; }
            //public Dictionary<int, int> Month { get; set; }
            public int[] Month { get { return month; } set { month = value; } }
            public int[] month = new int[12];
        }

        public List<UnusedRoles> unusedroles = new List<UnusedRoles>();
        public List<UnusedRolesOccurrence> unusedrolesoccurrence = new List<UnusedRolesOccurrence>();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Run();
        }

        public async void Run()
        {
            unusedroles.Clear();
            unusedrolesoccurrence.Clear();

            Dictionary<int, int> dictionary_month = new Dictionary<int, int>();

            //for (int i = 0; i < 12; i++) { dictionary_month.Add(i, 0); }
            int[] arr_month = new int[12];

            unusedroles.Add(new UnusedRoles { Username = "User1", Role = "A", Month = 0 });
            unusedroles.Add(new UnusedRoles { Username = "User1", Role = "A", Month = 0 });
            unusedroles.Add(new UnusedRoles { Username = "User1", Role = "B", Month = 0 });
            unusedroles.Add(new UnusedRoles { Username = "User2", Role = "A", Month = 0 });
            unusedroles.Add(new UnusedRoles { Username = "User2", Role = "B", Month = 0 });
            unusedroles.Add(new UnusedRoles { Username = "User2", Role = "B", Month = 0 });
            unusedroles.Add(new UnusedRoles { Username = "User3", Role = "C", Month = 0 });
            unusedroles.Add(new UnusedRoles { Username = "User3", Role = "C", Month = 0 });
            unusedroles.Add(new UnusedRoles { Username = "User3", Role = "C", Month = 0 });
            unusedroles.Add(new UnusedRoles { Username = "User4", Role = "A", Month = 0 });

            var tmp = unusedroles.Select(x => new { x.Username, x.Role }).Distinct();

            foreach (var item in tmp)
            {
                unusedrolesoccurrence.Add(new UnusedRolesOccurrence
                {
                    //Username = item.Username, Role = item.Role, Month = dictionary_month
                    Username = item.Username, Role = item.Role, Month = arr_month
                });
            }

            var result = await Find(0);

            foreach (var item in unusedrolesoccurrence)
            {
                //string line = "";
                //foreach (var pair in item.Month) {
                //    line = $"{line},{pair.Value}";
                //}
                string line = $"{item.Username},{item.Role}";
                foreach (int i in item.Month)
                {
                    line = $"{line},{i}";
                }
                //Debug.WriteLine($"{item.Username},{item.Role}{line}");
                Debug.WriteLine($"{line}");

            }
        }

        public async Task<bool> Find(int month)
        {
            await Task.Run(() =>
            {
                Parallel.ForEach(unusedrolesoccurrence, (UnusedRolesOccurrence item) =>
                {
                        int count = unusedroles.Count(x => x.Username == item.Username && x.Role == item.Role &&x.Month == month);
                        item.Month[month] = count;
                        Debug.WriteLine($"{item.Username},{item.Role},count={count},item.Month[{month}]={item.Month[month]}");
                });
            });

            return true;
        }

Ответы [ 2 ]

0 голосов
/ 09 сентября 2018

Так работает.

До:

        int[] arr_month = new int[12];

        var tmp = unusedroles.Select(x => new { x.Username, x.Role }).Distinct();

        foreach (var item in tmp)
        {
            unusedrolesoccurrence.Add(new UnusedRolesOccurrence
            {
                //Username = item.Username, Role = item.Role, Month = dictionary_month
                Username = item.Username, Role = item.Role, Month = arr_month
            });
        }

После:

    var tmp = unusedroles.Select(x => new { x.Username, x.Role }).Distinct();

    foreach (var item in tmp)
    {
        unusedrolesoccurrence.Add(new UnusedRolesOccurrence
        {
            //Username = item.Username, Role = item.Role, Month = dictionary_month
            Username = item.Username, Role = item.Role, Month = new int[12]
        });
    }
0 голосов
/ 08 сентября 2018

TL; DR: ваш массив месяцев статический, не делайте этого.

Следующий член вашего класса UnusedRolesOccurrence является общим для всех экземпляров этого класса во время установленной вами параллельной операции.

private static int[] month = new int[12];

Удалите статическое ключевое слово, и каждый экземпляр UnusedRolesOccurrence будет иметь свой собственный массив .month.

Примечание: у вас могут быть другие проблемы в этом коде, но ваш вопрос связан с этой проблемой здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...