Reputation: 25
The code bellow:
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; }
}
}
Gives errors is more than one thread is running. Can anyone help me with the reason why? Is this line:
fathers.Update(this.FatherProperties);
changes to this:
fathers.Update(father.GetFatherValues());
The code works.
Is this related to the access of the property? I can't figure out why. I tried to read many websites but still can't find the reason of this error.
Thanks for the help.
Upvotes: 1
Views: 261
Reputation: 992
First: Your excessive use of extension methods make the code very hard to read.
Second: You are pulling away the very collection you are using th compare. You use only ONE SplitService and its FatherProperties and you are changeing them in every call to split.Split(fathers). Since you are doing it multithreaded, you compare in one thread while another just puts a new fatherproperties collection in there. When using the GetFatherValues() again you are avoiding this behavior and therefore not getting an error.
Put the creation of the splitservice into the iteration.
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();
}
Upvotes: 0
Reputation: 9365
You are using the same instance of SplitService
for all your tasks.
Inside you are modifying it's member FatherProperties
.
Obviously, that's why you have this behavior.
Create a service for each task:
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);
};
Upvotes: 1