多线程中访问public List<Entity> Entities { get { lock(syncObjecct){return ....}} set{ lock(syncObject){....}}; Entities对象时,为什么循环遍历时有时候会发生错误(Note: 我已经加锁对象并且用for循环而不是foreach循环访问对象)。我的程序:private List<Entity> entities = new List<Entities>();public List<Entity> Entities { get { lock(syncObjecct){return ...entities.}} set{ lock(syncObject){....entities = value}}; private void Insert(Entity entity){Entities.add(entity);}private void Remove(){if (Entityes.Count >0 )Entities.Remove(0);}int main(){//多个线程添加删除访问Entities链表时候遍历有时会发生错误for (int i = 0; i <Entities.Count;i++) {var item = Entities[0]; //报错:集合已经被修改 }}
1 回答
慕无忌1623718
TA贡献1744条经验 获得超4个赞
)【异常的原因】
按您给出的代码,问题出在public List<Entity> Entities{get; set;}上:这个属性方法在获取List<Entity>实例的执行过程中利用了lock(){}来保持同步;但是,一旦这个属性方法执行结束就跳出了lock(){}的同步范围。这意味着:在主函数中所获取的List<Entity>实例已经不再受到lock的保护了!遍历集合发生将抛出异常(通常是“集合序数变化……”之类的异常)
2)【解决方法】
关键是为遍历集合的方法提供同步功能。见下面的代码
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; namespace ConsoleApplication1 { class Program { static EntityList list = new EntityList(); static void Main( string [] args) { //启动线程:向集合中添加 Thread threadAdding = new Thread(Adding); threadAdding.IsBackground = true ; threadAdding.Start(); //启动线程:从集合中删除 Thread threadRemoving = new Thread(Removing); threadRemoving.IsBackground = true ; threadRemoving.Start(); //启动线程:遍历集合 Thread threadWork = new Thread(Work); threadWork.IsBackground = true ; threadWork.Start(); Console.ReadKey(); } static void Adding() { int id = 0; while ( true ) { id++; list.Insert( new Entity() { Id = id, Gender = "Male" , Name = "Someone" + id.ToString() }); Thread.Sleep(750); } } static void Removing() { while ( true ) { list.Remove(); Thread.Sleep(1000); } } static void Work() { while ( true ) { //遍历集合 foreach ( var e in list) { Console.WriteLine(e.ToString()); } Console.WriteLine( "------------" ); Thread.Sleep(1000); } } } /// <summary> /// 实体对象 /// </summary> class Entity { public int Id { get ; set ; } public string Name { get ; set ; } public string Gender { get ; set ; } public override string ToString() { return string .Format( "Id={0} Name={1} Gender={2}" , Id, Name, Gender ); } } /// <summary> /// 实体对象列表(集合) /// </summary> class EntityList : IEnumerable<Entity> { object syncObject = new object (); List<Entity> list = new List<Entity>(); public void Insert(Entity entity) { lock (syncObject) { list.Add(entity); } } public void Remove() { lock (syncObject) { if (list.Count > 0) list.RemoveAt(0); } } //带同步功能的集合遍历接口 public IEnumerator<Entity> GetEnumerator() { lock (syncObject) { foreach ( var v in list) { yield return v; } } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this .GetEnumerator(); } } } |
- 1 回答
- 0 关注
- 87 浏览
添加回答
举报
0/150
提交
取消