我有一个Canvas
里面有很多小画布。如果我单击它们中的任何一个,它会创建一个带有特定方法的Thread
(例如,在主画布上添加另一个小画布并移动它)。当我点击一个特定按钮时,我需要让一些小画布成长。所以我尝试使用foreach
循环但应用程序崩溃并向我显示此错误:
InvalidOperationException:修改了集合;枚举操作可能无法执行
我认为这是因为有一个上下文切换,所以我添加了一个锁定方法,但问题仍在继续。我的代码如下:
private void BacteriaPsiEspecial(object sender , MouseButtonEventArgs e)
{
lock (sender)//Maybe here is the problem
{
//The application crashes here
foreach (Canvas LittleCanvas in CanvasSimulador.Children)
{
if(LittleCanvas.Uid.Equals("SomeId"))
{
//Method to make each one grow growMethod()
}
}
}
}
我不知道foreach
是否有效。我必须使用很多线程,因为所有的小画布都在主画布上不断移动。问题是,我该怎样做才能使那些画布受到growMethod()的影响?
答案 0 :(得分:0)
听起来你有多个线程会改变你试图foreach
的集合。简单地说,这不起作用。以下是我能想到的几个选项:
growMethod()
需要花费大量时间,您可以在迭代之前尝试获取列表的副本...... LINQ扩展方法.ToList()
或.ToArray()
应该可以正常工作。但是你可能仍然会遇到异常,所以你最终可能会添加重试逻辑......等等。您可以通过在访问和修改时锁定来限制对集合的访问:
private IEnumerable<Canvas> GetLittleChildren() {
lock(lockObject) {
return CanvasSimulador.Children.ToArray();
}
}
private IEnumerable<Canvas> AddChild(Canvas littleCanvas) {
lock(lockObject) {
CanvasSimulador.Children.Add(littleCanvas);
}
}
private IEnumerable<Canvas> RemoveChild(Canvas littleCanvas) {
lock(lockObject) {
CanvasSimulador.Children.Remove(littleCanvas);
}
}
我仍然不相信这是一个好方法,但它可能会有用......