C#多线程共享变量循环遍历

2025-03-09 18:05:59
推荐回答(1个)
回答1:

1)【异常的原因】

按您给出的代码,问题出在public List Entities{get; set;}上:这个属性方法在获取List实例的执行过程中利用了lock(){}来保持同步;但是,一旦这个属性方法执行结束就跳出了lock(){}的同步范围。这意味着:在主函数中所获取的List实例已经不再受到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);
            }
        }
    }

    /// 
    /// 实体对象
    /// 

    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
            );
        }
    }

    /// 
    /// 实体对象列表(集合)
    /// 

    class EntityList : IEnumerable
    {
        object syncObject = new object();
        List list = new List();
        public void Insert(Entity entity)
        {
            lock (syncObject)
            {
                list.Add(entity);
            }
        }
        public void Remove()
        {
            lock (syncObject)
            {
                if (list.Count > 0) list.RemoveAt(0);
            }
        }
        //带同步功能的集合遍历接口
        public IEnumerator GetEnumerator()
        {
            lock (syncObject)
            {
                foreach (var v in list)
                {
                    yield return v;
                }
            }
        }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
}