发生了未处理的异常。 System.InvalidOperationException:集合已被修改;枚举操作可能无法执行 在System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource 资源)
在System.Collections.Generic.List`1.Enumerator.MoveNextRare()
在System.Collections.Generic.List`1.Enumerator.MoveNext()
在System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
在System.Linq.Enumerable.Sum(IEnumerable`1 source)
在Check.get_TotalChange()
在CheckChanged(ICheck check)
如果我每天运行我的代码5次,就像2次那样会导致此错误,程序会崩溃..我的代码出了什么问题?我遵循了异常信息,我认为这是可能导致异常的代码。任何人都知道是什么类型的问题?
public decimal TotalChange
{
get
{
var change = (from IPayment payment in _payments where payment.Amount < 0 select payment.Amount).Sum();
var paid = (from IPayment payment in _payments select payment.Amount).Sum();
return paid <= Total && Total > 0 ? Math.Abs(change) : paid - Total;
}
}
我把它改为:
private readonly object _totalChangeLock = new object();
public decimal TotalChange
{
get
{
lock (_totalChangeLock)
{
var change =
(from IPayment payment in _payments where payment.Amount < 0 select payment.Amount).Sum();
var paid = (from IPayment payment in _payments select payment.Amount).Sum();
return paid <= Total ? Math.Abs(change) : paid - Total;
}
}
}
我也有2种修改_payments的方法。我也锁定了它们。希望不会引起任何问题。
public void AddPayment(IPayment payment)
{
lock (_paymentsLock)
{
if (_payments.Contains(payment)) return;
_payments.Add(payment);
}
}
public void RemovePayment(IPayment payment)
{
lock (_paymentsLock)
{
if (_payments.Contains(payment))
_payments.Remove(payment);
}
}
答案 0 :(得分:2)
最有可能在执行TotalChange属性代码时从另一个线程修改_payments变量。
如果是这样,请尝试避免对_payments变量进行多线程访问,或者在对_payments变量进行读/写访问时考虑使用锁定
lock(_lockerObject)
{
// Do operations that modify _payments collection
_payments.Add();//...
}
public decimal TotalChange
{
get
{
lock (_lockerObject)
{
var change = (from IPayment payment in _payments where payment.Amount < 0 select payment.Amount).Sum();
var paid = (from IPayment payment in _payments select payment.Amount).Sum();
}
return paid <= Total && Total > 0 ? Math.Abs(change) : paid - Total;
}
}
答案 1 :(得分:1)
有很多方法可以解决这个问题,最简单的方法是处理另一个列表,这样就可以添加_payments
:
public decimal TotalChange
{
get
{
lock(_syncObj)
{
var p = _payments.ToList();
}
var change = (from IPayment payment in p where payment.Amount < 0 select payment.Amount).Sum();
var paid = (from IPayment payment in p select payment.Amount).Sum();
return paid <= Total && Total > 0 ? Math.Abs(change) : paid - Total;
}
}
您还需要在添加项目时将其锁定:
lock(_syncObj)
{
_payments.Add();//...
}