Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Where后跟OrderBy是否要求ToList和lock以防止集合被修改异常?_C#_Locking_Enumeration - Fatal编程技术网

C# Where后跟OrderBy是否要求ToList和lock以防止集合被修改异常?

C# Where后跟OrderBy是否要求ToList和lock以防止集合被修改异常?,c#,locking,enumeration,C#,Locking,Enumeration,我有以下代码: lock (fullEventList) { ftl = fullEventList.Where(a => a != null) .OrderBy(a => a.Start) .ThenBy(a => a.TaskID) .ThenBy(a => a.Status).ToList(); } 正在引发异常(集合已

我有以下代码:

lock (fullEventList)
{
    ftl = fullEventList.Where(a => a != null)
                       .OrderBy(a => a.Start)
                       .ThenBy(a => a.TaskID)
                       .ThenBy(a => a.Status).ToList();
}
正在引发异常(集合已修改),该异常突出显示行的.OrderBy部分。 鉴于列表fullEventList周围有一个锁,我认为可能有另一个线程在修改列表。.Sort()的一些用法是修改列表,而不是返回新列表,但我还没有找到发生这种情况的地方


有没有办法保护此行不受其他地方修改的列表的影响

正如@xanatos在评论中指出的,在迭代列表时(从任何线程)修改列表将抛出异常

Linq在内部遍历列表

使用锁不会阻止另一个线程从另一个代码块修改列表,因此代码也必须锁定列表

处理列表的另一种方法是将它们视为不可变对象,而不是修改它们。如果要对列表中的项目进行排序,请在新列表中使用OrderBy(因此不会修改列表),然后在处理完后,将此新列表分配给旧列表变量

    var closureList = fullEventList.Where(a => a != null).ToList();
    ftl = closureList.Where(a => a != null)
                     .OrderBy(a => a.Start)
                     .ThenBy(a => a.TaskID)
                     .ThenBy(a => a.Status).ToList();

需要更多的内存,但线程的问题更少。不需要锁,因为每个线程都在自己的列表副本上操作

不,没有。。。你必须到处锁。我的印象是,你只需要锁修改列表的东西,没有锁就可以读取列表。那么,如果一个线程锁定并删除最后一个元素,同时另一个线程忽略锁,尝试读取最后一个元素,会发生什么情况?每次访问一个方法、属性或索引器时,在使用它之前,都应该
锁定
。。。事实上,如果没有写入程序(例如,所有数据都是在程序开始时写入的,并且集合永远不会被修改),那么任何数量的读卡器都可以在没有锁的情况下读取,这是有意义的。我想这会让我想到,为什么我以前从未在列表中使用过锁,而且没有任何问题?这是一个Android/Xamarin应用程序,通常我都在.Net/C中,很少使用列表和锁。直到现在才看到这种类型的异常。因为您没有使用多线程,或者您使用了
for
循环而不是
foreach
循环(间接地
foreach
检查集合是否已修改,然后抛出异常,而
for
不检查)。Linq方法在内部是big
foreach