我修改了枚举的集合但是,我把Lock放在它周围...... 它并没有说明我为什么会这样做 “集合已被修改;枚举操作可能无法执行。” 我不想解决它:“foreach(IObserver obs in _observers.ToList())”
代码是观察者模式:
class Program
{
static void Main(string[] args)
{
Subject sub = new Subject();
Obs1 obs1 = new Obs1(sub);
Obs2 obs2 = new Obs2(sub);
sub.Nodefiy();
sub.Nodefiy();
sub.Nodefiy();
sub.Nodefiy();
sub.Nodefiy();
sub.Nodefiy();
Console.ReadKey();
}
}
public interface IObserver
{
void Update(int data);
}
public interface ISubscrib
{
void Reg(IObserver obs);
void UnReg(IObserver obs);
void Nodefiy();
}
public class Subject : ISubscrib
{
private static Object _lock;
private List<IObserver> _observers;
private int data = 0;
public Subject()
{
_lock = new Object();
_observers = new List<IObserver>();
}
public void Reg(IObserver obs)
{
lock (_lock)
{
_observers.Add(obs);
}
}
public void UnReg(IObserver obs)
{
lock (_lock)
{
int ind = _observers.IndexOf(obs);
if (ind >= 0)
{
_observers.RemoveAt(ind);
}
}
}
public void Nodefiy()
{
data = data + 1;
lock (_lock)
{
int sentData = data;
//foreach (IObserver obs in _observers.ToList<IObserver>())
foreach (IObserver obs in _observers)
{
obs.Update(sentData);
}
}
}
}
public class Obs1 : IObserver
{
private ISubscrib _subj;
public Obs1(ISubscrib subj)
{
_subj = subj;
_subj.Reg(this);
}
public void Update(int data)
{
Console.WriteLine("Obs1: {0}", data);
}
}
public class Obs2 : IObserver
{
private ISubscrib _subj;
public Obs2(ISubscrib subj)
{
_subj = subj;
_subj.Reg(this);
}
public void Update(int data)
{
Console.WriteLine("Obs2: {0}", data);
if (data > 3)
{
_subj.UnReg(this);
}
}
}
谁能帮助我吗?
感谢...
答案 0 :(得分:2)
当你的Obj2在这个foreach循环中调用Update时,它将回到你的Subject对象并在同一个线程中修改这个_observers集合。这就是锁无法正常工作的原因。这不是同步问题。你的问题发生在同一个线程中。
我不确定您在此代码中尝试做什么,所以我无法继续帮助。
答案 1 :(得分:1)
锁与线程同步有关,我不确定为什么你认为这会对你有所帮助。
当您正在修改该集合时,您无法枚举集合(请参阅所有相关问题)。将你的foreach更改为:
for (int i = _observers.Count-1; i >= 0; i--) {
_observers[i].Update(sentData);
}
答案 2 :(得分:1)
问题是我认为......当您迭代_observers列表时,您还可以从另一个线程添加或修改该集合。
你可以同步线程,你应该这样做,因为如果你试图访问一个被删除的观察者,即使是像索引器一样使用for的解决方案也无济于事。
尝试查看Mutexes以实现一种方式,当一个线程迭代通过集合时,另一个线程将等到它完成后再修改集合。