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

多线程中访问publicList<Entity>Entities{get{lock(syncObjecct){return....}}set{lock(syncObjec... 多线程中访问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]; //报错:集合已经被修改
}

}
展开
 我来答
freeeeeewind
推荐于2018-04-12 · TA获得超过1万个赞
知道大有可为答主
回答量:3227
采纳率:94%
帮助的人:1364万
展开全部

1)【异常的原因】

按您给出的代码,问题出在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();
        }
    }
}
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式