Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 线程和列表<&燃气轮机;收集_C#_.net_Multithreading_Collections_Thread Safety - Fatal编程技术网

C# 线程和列表<&燃气轮机;收集

C# 线程和列表<&燃气轮机;收集,c#,.net,multithreading,collections,thread-safety,C#,.net,Multithreading,Collections,Thread Safety,我的List集合名为List 我有两条线。 一个线程正在枚举所有列表元素并添加到集合中。 第二个线程正在枚举所有列表元素并从中删除 如何使其线程安全? 我尝试创建全局对象“MyLock”,并在每个线程函数中使用lock(MyLock)块,但没有成功 您能帮助我吗?您应该能够直接锁定您的列表: lock(list) { //work with list here } 但是,在枚举时从列表中添加/删除可能会导致异常…您应该能够直接锁定列表: lock(list) { //work

我的
List
集合名为
List

我有两条线。 一个线程正在枚举所有列表元素并添加到集合中。 第二个线程正在枚举所有列表元素并从中删除

如何使其线程安全? 我尝试创建全局对象“MyLock”,并在每个线程函数中使用lock(MyLock)块,但没有成功


您能帮助我吗?

您应该能够直接锁定您的列表:

lock(list) {
    //work with list here
}

但是,在枚举时从列表中添加/删除可能会导致异常…

您应该能够直接锁定列表:

lock(list) {
    //work with list here
}

但是,在枚举列表时从列表中添加/删除可能会导致异常…

锁定您的
列表的
SyncRoot


有关如何正确使用它的更多信息,请参见
列表的
SyncRoot
锁定:


关于如何正确使用它的更多信息,可以在不了解您的程序和要求的情况下找到,我认为这是一个“坏主意”。在遍历
列表的内容时更改该列表
,很可能会引发异常


您最好使用
队列
而不是
列表
,因为
队列
的设计考虑了同步。

在不了解更多程序和需求的情况下,我会说这是一个“坏主意”。在遍历
列表的内容时更改该列表
,很可能会引发异常


您最好使用
队列
而不是
列表
,因为
队列
的设计考虑了同步。

如果您可以访问.NET 4.0,则可以使用类或带有ConcurrentQueue支持的类。它完全执行您试图执行的操作,不需要任何锁定。如果列表中没有可用项,BlockingCollection将使线程等待

从ConcurrentQueue中删除的示例如下

ConcurrentQueue<MyClass> cq = new ConcurrentQueue<MyClass>();

void GetStuff()
{
    MyClass item;
    if(cq.TryDeqeue(out item))
    {
        //Work with item
    }
}
ConcurrentQueue cq=新的ConcurrentQueue();
void GetStuff()
{
MyClass项目;
if(cq.TRYDEQUE(外项))
{
//处理项目
}
}
这将尝试删除项目,但如果没有可用项目,则不会执行任何操作

BlockingCollection<MyClass> bc = BlockingCollection<MyClass>(new ConcurrentQueue<MyClass>());

void GetStuff()
{
    if(!bc.IsCompleated) //check to see if CompleatedAdding() was called and the list is empty.
    {
        try
        {
            MyClass item = bc.Take();
            //Work with item
        }
        catch (InvalidOpperationExecption)
        {
            //Take is marked as completed and is empty so there will be nothing to take
        }
    }
}
BlockingCollection bc=BlockingCollection(新ConcurrentQueue());
void GetStuff()
{
if(!bc.iscompleted)//检查是否调用了completedading(),列表是否为空。
{
尝试
{
MyClass item=bc.Take();
//处理项目
}
捕获(InvalidUpperationExection)
{
//Take标记为已完成且为空,因此将不会有任何内容可获取
}
}
}

这将阻止并等待
Take
,直到列表中有可用的内容。完成后,您可以调用
CompleteAdding()
并在列表变为空时抛出一个execption,而不是阻塞。

如果您可以访问.NET 4.0,则可以使用该类或带有ConcurrentQueue支持的。它完全执行您试图执行的操作,不需要任何锁定。如果列表中没有可用项,BlockingCollection将使线程等待

从ConcurrentQueue中删除的示例如下

ConcurrentQueue<MyClass> cq = new ConcurrentQueue<MyClass>();

void GetStuff()
{
    MyClass item;
    if(cq.TryDeqeue(out item))
    {
        //Work with item
    }
}
ConcurrentQueue cq=新的ConcurrentQueue();
void GetStuff()
{
MyClass项目;
if(cq.TRYDEQUE(外项))
{
//处理项目
}
}
这将尝试删除项目,但如果没有可用项目,则不会执行任何操作

BlockingCollection<MyClass> bc = BlockingCollection<MyClass>(new ConcurrentQueue<MyClass>());

void GetStuff()
{
    if(!bc.IsCompleated) //check to see if CompleatedAdding() was called and the list is empty.
    {
        try
        {
            MyClass item = bc.Take();
            //Work with item
        }
        catch (InvalidOpperationExecption)
        {
            //Take is marked as completed and is empty so there will be nothing to take
        }
    }
}
BlockingCollection bc=BlockingCollection(新ConcurrentQueue());
void GetStuff()
{
if(!bc.iscompleted)//检查是否调用了completedading(),列表是否为空。
{
尝试
{
MyClass item=bc.Take();
//处理项目
}
捕获(InvalidUpperationExection)
{
//Take标记为已完成且为空,因此将不会有任何内容可获取
}
}
}

这将阻止并等待
Take
,直到列表中有可用的内容。完成后,您可以调用
CompleteAdding()
并在列表变为空时抛出一个execption,而不是阻塞。

您可以实现自己版本的
IList
,该版本包装了基础
列表
,以在每次方法调用时提供锁定

public class LockingList<T> : IList<T>
{
    public LockingList(IList<T> inner)
    {
        this.Inner = inner;
    }

    private readonly object gate = new object();
    public IList<T> Inner { get; private set; }

    public int IndexOf(T item)
    {
        lock (gate)
        {
            return this.Inner.IndexOf(item);
        }
    }

    public void Insert(int index, T item)
    {
        lock (gate)
        {
            this.Inner.Insert(index, item);
        }
    }

    public void RemoveAt(int index)
    {
        lock (gate)
        {
            this.Inner.RemoveAt(index);
        }
    }

    public T this[int index]
    {
        get
        {
            lock (gate)
            {
                return this.Inner[index];
            }
        }
        set
        {
            lock (gate)
            {
                this.Inner[index] = value;
            }
        }
    }

    public void Add(T item)
    {
        lock (gate)
        {
            this.Inner.Add(item);
        }
    }

    public void Clear()
    {
        lock (gate)
        {
            this.Inner.Clear();
        }
    }

    public bool Contains(T item)
    {
        lock (gate)
        {
            return this.Inner.Contains(item);
        }
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        lock (gate)
        {
            this.Inner.CopyTo(array, arrayIndex);
        }
    }

    public int Count
    {
        get
        {
            lock (gate)
            {
                return this.Inner.Count;
            }
        }
    }

    public bool IsReadOnly
    {
        get
        {
            lock (gate)
            {
                return this.Inner.IsReadOnly;
            }
        }
    }

    public bool Remove(T item)
    {
        lock (gate)
        {
            return this.Inner.Remove(item);
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        lock (gate)
        {
            return this.Inner.ToArray().AsEnumerable().GetEnumerator();
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        lock (gate)
        {
            return this.Inner.ToArray().GetEnumerator();
        }
    }
}
公共类锁定列表:IList
{
公共锁定列表(IList内部)
{
这个。内=内;
}
私有只读对象门=新对象();
公共IList内部{get;私有集;}
公共整数索引(T项)
{
锁(门)
{
返回此.Inner.IndexOf(项目);
}
}
公共空白插入(整数索引,T项)
{
锁(门)
{
本.内.插入(索引,项目);
}
}
公共无效删除(整数索引)
{
锁(门)
{
this.Inner.RemoveAt(索引);
}
}
公共T此[int索引]
{
得到
{
锁(门)
{
返回这个。内部[索引];
}
}
设置
{
锁(门)
{
this.internal[索引]=值;
}
}
}
公共作废新增(T项)
{
锁(门)
{
本.内.加(项);
}
}
公共空间清除()
{
锁(门)
{
this.internal.Clear();
}
}
公共布尔包含(T项)
{
锁(门)
{
返回此.Inner.Contains(项目);
}
}
public void CopyTo(T[]数组,int arrayIndex)
{
锁(门)
{
this.internal.CopyTo(array,arrayIndex);
}
}
公共整数计数
{
得到
{