【发布时间】:2017-03-17 17:00:18
【问题描述】:
我有一个已通过属性绑定到我的 GUI 的 ObservableCollection 日志
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 我认为这需要一些时间来制作副本。
如果我能提供澄清,请告诉我。 谢谢,
戴夫
【问题讨论】:
-
documentation 不保证任何有用的方法或属性都是线程安全的,因此您必须假设它们都不是。您可以在您的日志记录方法中使用
lock(您将在其中添加到Logs集合)以及有问题的ToList。这似乎是唯一确定的解决方法。可能覆盖您的类中从ObservableCollection派生的所有插入等方法,以使用SyncRoot属性进行锁定。 -
所有好的答案,我感谢大家!可惜只能选1个。
标签: .net thread-safety observablecollection