下面的代码:
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());
代码有效。
这与财产的使用有关吗?我不知道为什么。 我尝试阅读许多网站,但仍然找不到此错误的原因。
感谢您的帮助。
答案 0 :(得分:1)
您正在为所有任务使用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);
};
答案 1 :(得分:0)
首先:过度使用扩展方法会使代码很难阅读。
第二:您正在拿走正在使用的收藏集。您仅使用一个SplitService及其父属性,并且在每次对split.Split(fathers)的调用中都对其进行了更改。由于您正在执行多线程操作,因此可以在一个线程中进行比较,而在另一个线程中只需在其中放入一个新的父亲属性集合。再次使用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();
}