我刚刚意识到,通过阅读StackOverflow上的一些问题和答案,+=在C#(或者我猜,其他.net语言)中添加事件处理程序会导致常见的内存泄漏......
我过去曾多次使用这样的事件处理程序,并且从未意识到它们可能导致或导致我的应用程序中的内存泄漏.
这是如何工作的(意思是,为什么这实际上会导致内存泄漏)?
我该如何解决这个问题?是否-=足够使用相同的事件处理程序?
是否有常见的设计模式或最佳实践来处理这样的情况?
示例:我应该如何处理具有许多不同线程的应用程序,使用许多不同的事件处理程序在UI上引发多个事件?
是否有任何好的和简单的方法可以在已经构建的大型应用程序中有效地监控它?
我已经看到很多关于这个问题的讨论,但也许我只是太多的新手才能得到它.如果我有一个可观察的集合,它是msdn示例中的"PersonNames"集合(http://msdn.microsoft.com/en-us/library/ms748365.aspx),如果a PersonName是,我会获得对View的更新添加或删除等.当我更改属性时,我想获得我的视图的更新PersonName.就像我改名字一样.我可以OnPropertyChanged为每个属性实现并让这个类派生出来INotifyPropertyChanged,并且似乎按预期调用.我的问题是,View如何从ObservableCollection更改属性获取更新数据不会导致任何事件ObservableCollection.这可能是非常简单的事情,但为什么我似乎无法找到一个令我惊讶的例子.任何人都可以为我阐明这一点,或者对示例有任何指示我会非常感激.我们在当前的WPF应用程序的多个位置都有这种情况,并且正在努力搞清楚.
"通常,负责显示数据的代码会为PropertyChanged当前显示在屏幕上的每个对象添加一个事件处理程序."
有人可以举个例子说明这意味着什么吗?我查看结合我ViewModel其中有一个ObservableCollection.此集合由RowViewModel具有支持PropertiesChanged事件的属性组成.但我无法弄清楚如何使集合更新自己,以便更新我的视图.
我有一个可观察的集合...... SelectableDataContext<T>在泛型类SelectableDataContext<T>中......有两个私有成员变量
当IsSelected属性发生更改时...我的集合的已更改属性未触发.
我认为它应该解雇...因为它Reset在INotifyCollectionChangedAction.
我正在尝试挂钩INotifyPropertyChanged集合中对象的事件.
我在这个问题上见过的每一个答案都说要按如下方式处理:
void NotifyingItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if( e.NewItems != null )
{
foreach( INotifyPropertyChanged item in e.NewItems )
{
item.PropertyChanged += new PropertyChangedEventHandler(CollectionItemChanged);
}
}
if( e.OldItems != null )
{
foreach( ValidationMessageCollection item in e.OldItems )
{
item.PropertyChanged -= CollectionItemChanged;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,只要开发人员调用Clear()NotifyingItems集合,这就完全失败了.发生这种情况时,该事件处理函数被调用,e.Action == Reset并且两个e.NewItems和e.OldItems等于null(我希望后者包含的所有项目).
问题是这些物品不会消失,而且它们不会被破坏,它们不再被当前的班级监控 - 但由于我从未有机会取消映射它们PropertyChangedEventHandler- 它们一直在调用我的CollectionItemChanged处理程序他们已从我的NotifyingItems列表中清除.如何以这种"完善的"模式处理这种情况?
请注意,我正在尝试使用NotifyCollectionChangedAction.Add操作而不是.Reset.后者确实有效,但对于大型集合来说效率不高.
所以我继承了ObservableCollection:
public class SuspendableObservableCollection<T> : ObservableCollection<T>
Run Code Online (Sandbox Code Playgroud)
由于某种原因,这段代码:
private List<T> _cachedItems;
...
public void FlushCache() {
if (_cachedItems.Count > 0) {
foreach (var item in _cachedItems)
Items.Add(item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add, (IList<T>)_cachedItems));
}
}
Run Code Online (Sandbox Code Playgroud)
抛出 一个集合添加事件是指不属于集合的项目
这似乎是BCL的一个错误?
我可以在调用OnCollectionChanged之前逐步查看将新项添加到this.Items
哇
刚刚发现了一个惊人的发现.这些方法都不适合我(flush,addrange),因为只有当这个集合绑定到我的Listview时才会触发错误!
TestObservableCollection<Trade> testCollection = new TestObservableCollection<Trade>();
List<Trade> testTrades = new List<Trade>();
for (int i = 0; i < 200000; i++)
testTrades.Add(t);
testCollection.AddRange(testTrades); // no problems here..
_trades.AddRange(testTrades); // this one is bound to ListView .. BOOOM!!!
Run Code Online (Sandbox Code Playgroud)
总之,ObservableCollection确实支持添加增量列表,但ListView不支持.Andyp想出了一个解决方法,使其适用于下面的CollectionView,但是由于调用了.Refresh(),这与调用OnCollectionChanged(.Reset)没什么不同.