Передача свойства экземпляра статическому методу в Async Tasks - PullRequest
0 голосов
/ 13 ноября 2018

код ниже:

namespace ConsoleApp2
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    class Program
    {
        static async Task Main(string[] args)
        {
            var split = new SplitService();

            var tasks = new List<Task>();
            for (var nI = 0; nI < 10; nI++)
            {
                var fathers = new List<Father> { new Father { Id = Guid.NewGuid() } };

                var task = new Task (() => split.Split(fathers));
                tasks.Add(task);
            };

            foreach (var task in tasks)
            {
                task.Start();
            }

            Console.ReadKey();
        }
    }

    public class SplitService
    {
        public IEnumerable<Father> Split(List<Father> fathers)
        {
            this.FatherProperties = fathers.GetFatherValues();

            this.RecalculateProperties(fathers);

            return fathers;
        }

        public List<FatherProperties> FatherProperties { get; private set; } = new List<FatherProperties>();

        public void RecalculateProperties(List<Father> fathers)
        {
            fathers.Update(this.FatherProperties);
        }
    }

    public static class FatherExtensions
    {
        public static List<FatherProperties> GetFatherValues(this List<Father> fathers)
        {
            return new List<FatherProperties>
            {
                new FatherProperties
                {
                    FatherId = fathers.FirstOrDefault().Id
                }
            };
        }

        public static void Update(this List<Father> fathers, List<FatherProperties> properties)
        {
            foreach (var father in fathers)
            {
                var match =
                    ( 
                     from value in properties
                     where value.FatherId == father.Id
                     select new
                     {
                         father.Id
                     }).SingleOrDefault();

                if (match == null)
                {
                    Console.WriteLine("Error");
                }
                else
                {
                    Console.WriteLine(match.Id); 
                }
            }
        }
    }

    public class Father
    {
        public Guid Id { get; set; }
    }

    public class FatherProperties
    {
        public Guid FatherId { get; set; }
    }
}

Выдает ошибки, если запущен более одного потока. Кто-нибудь может мне помочь с причиной почему? Эта строка:

fathers.Update(this.FatherProperties);

изменяется на это:

fathers.Update(father.GetFatherValues());

Код работает.

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

Спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Вы используете один и тот же экземпляр SplitService для всех своих задач. Внутри вы изменяете его член FatherProperties.

Очевидно, именно поэтому у вас такое поведение.

Создать сервис для каждой задачи:

for (var nI = 0; nI < 10; nI++)
{
    var split = new SplitService(); // <-- a dedicated service for each

    var fathers = new List<Father> { new Father { Id = Guid.NewGuid() } };
    var task = new Task (() => split.Split(fathers));
    tasks.Add(task);
};
0 голосов
/ 13 ноября 2018

Во-первых: чрезмерное использование методов расширения делает код очень сложным для чтения.Второе: вы отбираете ту коллекцию, которую используете для сравнения.Вы используете только ОДИН SplitService и его FatherProperties, и вы меняете их при каждом вызове split.Split (отцы).Поскольку вы делаете это многопоточным, вы сравниваете в одном потоке, в то время как другой просто помещает туда новую коллекцию отца свойств.При повторном использовании GetFatherValues ​​() вы избегаете этого поведения и, следовательно, не получаете ошибку.

Поместите создание splitservice в итерацию.

static void Main(string[] args)
    {
        var tasks = new List<Task>();
        for (var nI = 0; nI < 100; nI++)
        {
            var fathers = new List<Father> { new Father { Id = Guid.NewGuid() } };
            var split = new SplitService();
            var task = new Task(() => split.Split(fathers));
            tasks.Add(task);
        };

        foreach (var task in tasks)
        {
            task.Start();
        }

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