我有一个 ObservableCollection 的日志,我通过一个属性绑定(bind)到我的 GUI
public ObservableCollection<ILog> Logs {get; private set;}
需要在其他地方显示日志的子集,所以我有:
public ObservableCollection<ILog> LogsForDisplay
{
get
{
ObservableCollection<ILog> displayLogs = new ObservableCollection<ILog>();
foreach (Log log in Logs.ToList()) // notice the ToList()
{
if (log.Date != DateTime.Now.Day)
continue;
displayLogs.Add(log);
}
return displayLogs;
}
在我添加“ToList()”之前,我偶尔会遇到关于“集合已修改;枚举操作可能无法执行”的异常。这是有道理的——当我迭代它时,有人可以添加到日志中。我从 Collection was modified; enumeration operation may not execute 得到了“ToList”的想法这似乎表明 ToList 是要走的路,并暗示它是线程安全的。但是 ToList() 线程安全吗?我假设在内部它必须使用列表并对其进行迭代?如果有人同时添加到该列表中怎么办?仅仅因为我没有看到问题并不意味着没有问题。
我的问题。
ToList() 线程是否安全,如果不是,保护日志的最佳模式是什么?如果 ToList() 是线程安全的,你有引用吗?
奖金问题。如果要求发生变化并且我需要在 GUI 上显示的只是 LogsForDisplay 而不是 Logs,我可以将 Logs 更改为可以解决问题的其他内容吗?比如 ImmutableList ?然后我不必调用 ToList<> ,我认为这需要一些时间来制作副本。
让我知道我是否可以提供澄清。
谢谢,
戴夫
最佳答案
ToList
的执行扩展方法归结为通过 Array.Copy
将项目从一个数组复制到另一个数组。方法,其中隐藏 Collection was modified
您的错误不是线程安全的,当在 Array.Copy
期间更改基础项目时,您可能会遇到奇怪的行为调用。
我建议它使用CollectionView
对于绑定(bind),我在类似的情况下使用了很长时间,到目前为止没有遇到任何问题。
// somewhere in .ctor or other init-code
var logsForDisplay = new CollectionView(this.Logs);
logsForDisplay.Predicate = log => ((Log)log).Date == DateTime.Now.Day;
public CollectionView LogsForDisplay { get { return this.logsForDisplay; } }
你可以有另一个
CollectionView
对于不同的用例,例如:// somewhere in .ctor or other init-code
var yesterdaysLogs = new CollectionView(this.Logs);
yesterdaysLogs.Predicate = log => ((Log)log).Date == DateTime.Now.AddDays(-1).Day;
public CollectionView YesterdaysLogs{ get { return this.yesterdaysLogs; } }
关于.net - .NET ObservableCollection<> ToList() 线程安全吗?如果没有,如何进行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42863249/