c# - 当听众退订时,我可以收到通知吗?
问题描述
概括
- 我有一个简单的类,它公开了 type 的属性
ReadOnlyObservableCollection
。 - 第一次访问此属性时,会生成相当多的数据。
- 生成的数据是时间相关的,因此会随着时间而改变——因此需要属性是 type
ReadOnlyObservableCollection
。 - 这按预期工作,但是生成的数据集足够大,可以保证在应用程序的整个生命周期内我会遇到内存问题。
问题
我需要能够删除对生成数据的引用,以便 GC 可以收集这些数据。ReadOnlyObservableCollection
但问题是,除非我知道- 或者更准确地说是底层INotifyCollectionChanged.CollectionChanged
事件没有侦听器,否则我不能这样做。
当侦听器取消订阅事件而不实现所述事件时,有没有一种方法可以轻松地通知我?
一种相当简单但可能有点笨拙的解决方法是跟踪所有具有活动数据的 Storage 对象,CleanDataSet
如果没有INotifyCollectionChanged.CollectionChanged
事件的侦听器,则每隔一段时间调用该方法。
示例代码
public class Storage
{
//The regular computation of the data set is not shown as it is not relevant
//to the issue at hand.
public ReadOnlyObservableCollection<String> Data
{
get
{
if (DataList == null)
{
DataList = new ObservableCollection<String>();
DataReadOnly = new ReadOnlyObservableCollection<String>(DataList);
ComputeDataSet();
//I require a way of 'listening' when the
//DataList.CollectionChanged gains or loses a subscriber.
}
return DataReadOnly;
}
}
private ReadOnlyObservableCollection<String> DataReadOnly;
private ObservableCollection<String> DataList;
private void ComputeDataSet()
{
Random random = new Random();
for (Int32 counter = 0; counter < 10000; counter++)
DataList.Add(random.Next().ToString());
}
private void CleanDataSet()
{
DataReadOnly = null;
DataList = null;
}
}
解决方案
ReadOnlyObservableCollection.CollectionChanged
您可以使用虚拟的事实,null
如果没有订阅者,则返回事件:
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
public class Program
{
public static void Main()
{
var innerCollection = new ObservableCollection<string>() { "foo", "bar" };
var collection = (INotifyCollectionChanged)new MyReadOnlyObservableCollection<string>(innerCollection);
collection.CollectionChanged += Handler;
innerCollection.Add("baz");
collection.CollectionChanged -= Handler;
}
private static void Handler(object sender, NotifyCollectionChangedEventArgs e)
{
Console.WriteLine(e.NewItems[0]);
}
}
public class MyReadOnlyObservableCollection<T> : ReadOnlyObservableCollection<T>
{
public MyReadOnlyObservableCollection(ObservableCollection<T> list) : base(list) { }
private event NotifyCollectionChangedEventHandler InnerEvent;
protected override event NotifyCollectionChangedEventHandler CollectionChanged
{
add
{
if (InnerEvent == null)
{
Console.WriteLine("Got our first subscriber");
}
InnerEvent += value;
}
remove
{
InnerEvent -= value;
if (InnerEvent == null)
{
Console.WriteLine("There are no more subscribers");
}
}
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
InnerEvent?.Invoke(this, args);
}
}
我们覆盖CollectionChanged
事件,并提供我们自己的添加和删除处理程序。这些处理程序委托给内部事件(我们可以在这里使用委托,但事件+=
是线程安全的,而委托不是)。在 remove 处理程序中,我们还测试内部事件是否为null
: 如果是,则不再有订阅者。
我们还需要重写OnCollectionChanged
来调用我们的内部事件。
然而,此时我们几乎重写了ReadOnlyObservableCollection
:它不是一个大类。
推荐阅读
- ruby-on-rails-6 - ActiveStorage::FileNotFoundError(使用数据库后端)
- c# - 有什么方法可以避免在 iText 7 中加载 XMP 元数据?
- regex - RegEx 不匹配的信息
- python - TFBertForSequenceClassification Keras model.layers 信息详情为空?如何检查模型?
- python - python输出没有很多间距
- php - PHP中具有多重继承的类的存储库+工厂模式实现?
- kubernetes - 如何从 Minikube 连接到在 localhost 上运行的 MongoDB
- java - Spring Boot 2.2.5 获取post请求参数
- hash - 两个不同字符串具有相同哈希的概率?
- c++ - c ++字符串没有被重置