C# 锁定/并发问题

C# 锁定/并发问题,c#,multithreading,concurrency,locking,C#,Multithreading,Concurrency,Locking,我有以下C#代码: 1。列表边缘列表; 2. 3.bandEdgeList=CicApplication.BandEdgeCache.Where(row=>row.Coater==Coater.ToList(); 4.foreach(带边列表中的带边) 5.{ 6. 7. 8. } 我的问题是。在第3行填充“bandEdgeList”后,如果另一个线程修改CicApplication.BandEdgeCache的内容,“bandEdgeList”的内容是否会无效?我在CicAppl

我有以下C#代码:

1。列表边缘列表;
2.
3.bandEdgeList=CicApplication.BandEdgeCache.Where(row=>row.Coater==Coater.ToList();
4.foreach(带边列表中的带边)
5.{
6.
7.
8.       }

我的问题是。在第3行填充“bandEdgeList”后,如果另一个线程修改CicApplication.BandEdgeCache的内容,“bandEdgeList”的内容是否会无效?我在CicApplication.BandEdgeCache getter/setter中有一个锁。但是我想知道是否应该在这段代码周围加上一个锁,这样当我使用“bandEdgeList”时,CicApplication.BandEdgeCache的内容不会更改。

不是自动的,但这仍然不是线程安全的。它可能会抛出一个
InvalidOperationException

调用
ToList
后,其将保存这些引用的副本。但是,如果另一个线程在这种情况下修改了BandEdgeCache,那么坏事情就会发生

因此,您应该锁定对
BandEdgeCache
的所有引用


但是按照保存的列表,这是安全的,但是修改任何
BandEdge
在没有一些锁定的情况下都不是线程安全的。

bandEdgeList
将是一个独立的副本(因为您使用的是
ToList()
),所以不需要锁定


但是,正如@Daniel A.White所评论的,您需要锁定创建该副本的LINQ语句。

如果CicApplication.BandEdgeCache的getter返回对集合的引用,则锁定它对您没有帮助

CicApplication.BandEdgeCache{
  get{lock(_myCollection){return _myCollection;}}
}
返回引用,但一旦它返回就退出了锁,因此对getter返回的集合的引用使用Where()函数是在锁之外完成的,并且不是线程安全的。另一个线程可以很高兴地更改集合,而Where正在迭代,因为锁没有被持有-Daniel是正确的,如果另一个线程在生成列表时更改集合,将引发InvalidOperationException


生成列表后,可以更改原始集合,而不会影响对新列表的访问。

如果
BandEdgeCache
也是可编辑集合,则您可能会在本地列表中丢失项目,可能会有不符合
涂布机条件的项目,或者可能在您的列表中,除了下面答案中的问题之外,不再在
BandEdgeCache
集合中。它将是一个独立的副本,但为了使它成为独立副本,
BandEdgeCache
需要锁定。我今天学到了一些东西。。。我以为收费表实际上没有复制,你必须用ToArray来复制。。。谢谢Oded。@jsobo-它只复制引用。
CicApplication.BandEdgeCache{
  get{lock(_myCollection){return _myCollection;}}
}