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);
}
}
公共整数计数
{
得到
{