是否在迭代中编辑集合
本文关键字:编辑 集合 迭代 是否 | 更新日期: 2023-09-27 18:05:40
前言
我正在构建一个从互联网上抓取一些数据的应用程序。抓取的数据需要实时更新,所以我运行了一个无限循环每次检查以前的页面源是否已更改。所有这些数据都存储在ObservableCollection
中,如下所示:
private static ObservableCollection<Models.Event> _allMatches = new ObservableCollection<Models.Event>();
public ObservableCollection<Models.Event> AllMatches
{
get { return _matches; }
}
该ObservableCollection
在ListView
中绑定如下:
<CollectionViewSource Source="{Binding AllMatches}" x:Key="GroupedItems">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="MatchNation" />
<PropertyGroupDescription PropertyName="MatchLeague" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
CollectionViewSource
帮助我用GroupStyle
来组织ListView
中的数据,在这种情况下用于Nation -> League
。
问题开始
我将尝试创建一个简单的示例代码来更好地解释这个问题。因此,每个抓取的数据都与一个事件相匹配,所以我在ObservableCollection
中基本上有一个事件列表。
示例代码:
string oldData = null;
List<Event> matchListAll = new List<Event>();
while(true)
{
string data = new WebClient().DownloadString("websiteLink");
if(data != oldData) //There is an update! Get the new content
{
//code for scrape the event
foreach(var item in ItemScraped)
{
Event @event = new Event(); //this will contain the details of event scraped
@event.Date = item.Date; //and so on...
matchListAll.Add(@event); //Add the event to a list
}
//when the scraping iteration is over I put all of this event in the ObservableCollection
AddAllListItem(matchListAll);
}
}
现在上面的代码非常简单,从互联网上获取事件并将其放入一个对象中,就这样。当抓取完成时,我调用AddAllListItem
,这个方法将对ListView中绑定的ObservableCollection
进行估价。
这种方法的结构是:
private void AddAllListItem(List<Event> matches)
{
var allCollection = VM.AllMatches; //Access to AllMatches through the Vm (VM contain the ViewModel instance)
foreach (var @event in matches) //Iterate through the element scraped
{
//Add the scraped element to ObservableCollection so I can see it.
allCollection.Add(new Event
{
MatchDate = @event.MatchDate,
...
};
}
}
此代码存在严重问题。我想有人已经知道会发生什么了。
特别是,同时我在ObservableCollection中添加了AddAllListItem
方法再次调用,并且我作为参数传递的matches项发生了更改。这将生成一个例外:
集合已修改。枚举操作可能无法执行。
如何解决这种情况
我已经阅读了这里关于这个问题的几个问题,以及其他建议使用.ToList
或.ToArray
的问题,但我有一个ObservableCollection,同时我在屏幕上显示了我也需要更新的元素
我从来没有遇到过这样的情况,我希望有人能帮助我了解解决问题,谢谢。
也许这会对你有所帮助。
public class AsyncObservableCollection<T> : ObservableCollection<T>
{
private readonly object lockList = new object();
public object LockList
{
get { return lockList; }
}
public override event NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
var eh = CollectionChanged;
if (eh != null)
{
Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
let dpo = nh.Target as DispatcherObject
where dpo != null
select dpo.Dispatcher).FirstOrDefault();
if (dispatcher != null && dispatcher.CheckAccess() == false)
{
dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
}
else
{
foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
nh.Invoke(this, e);
}
}
}
new public void Remove(T item)
{
lock (lockList)
{
base.Remove(item);
}
}
new public void Add(T item)
{
lock (lockList)
{
base.Add(item);
}
}
public void AddByCheckExistence(T item)
{
lock (lockList)
{
if(!this.Contains(item))
{
base.Add(item);
}
}
}
}