我有ObservableCollection,它包含Item,每个Item都包含事件MessageEvent,在其上订阅一些匿名方法。主要问题是为什么在Items.Clear();
匿名之后还活着?
的Xaml:
<Grid>
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
代码:
namespace WpfApplication207
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Data D = new Data();
public MainWindow()
{
InitializeComponent();
DataContext = D;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
D.CleanCollection();
}
}
public class Item
{
public int id { get; set; }
public delegate void SendMessage (int i);
public event SendMessage MessageEvent;
public Item()
{
MessageEvent += (o) => { Console.WriteLine("Bad thing happens"); };
UpdateAsync();
}
public void UpdateAsync()
{
Action Test = new Action(DoSomeWork);
IAsyncResult result = Test.BeginInvoke(null,null);
}
public void DoSomeWork()
{
while(true)
{
System.Threading.Thread.Sleep(3000);
if (MessageEvent!=null)
{
MessageEvent(1);
}
}
}
}
public class Data
{
public ObservableCollection<Item> Items { get; set; }
public Data()
{
Items = new ObservableCollection<Item>();
Items.Add(new Item { id = 1});
}
public void CleanCollection()
{
Items.Clear();
}
}
答案 0 :(得分:2)
主要问题是为什么
Items.Clear();
匿名之后还活着?
因为使用items.Clear()
并不意味着项目会被垃圾收集。它只表示ObservableCollection<T>
不再拥有对这些项的引用,如果他是唯一一个这样的项,那么只有在下一个GC中才会收集这些项,其中下一个GC时间是任意的时间由运行时确定。
如果您希望项目停止打印这些消息,您可以做两件事:
Item
类一旦不再需要使用的物品,请使用一次性图案取消注册:
public class Item : IDisposable
{
public int id { get; set; }
private Action action;
public event SendMessage MessageEvent;
public Item()
{
action = () => Console.WriteLine("Bad thing happens");
MessageEvent += action;
UpdateAsync();
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (!disposing)
return;
MessageEvent -= action;
}
}
public class Data
{
public ObservableCollection<Item> Items { get; set; }
public Data()
{
Items = new ObservableCollection<Item>();
Items.Add(new Item { id = 1});
}
public void CleanCollection()
{
foreach (var item in Items)
{
item.Dispose();
}
items.Clear();
}
}