多線程中訪問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 關注
- 107 瀏覽
添加回答
舉報
0/150
提交
取消