Reputation: 3442
I have ObservableCollection which holds Item, every Item contains event MessageEvent on which subscribing some anonymous method. The main question is why after Items.Clear();
anonymous still alive?
Xaml:
<Grid>
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
Code:
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();
}
}
Upvotes: 1
Views: 66
Reputation: 149518
The main question is why after
Items.Clear();
anonymous still alive?
Because using items.Clear()
does not mean the items get garbage collected. It only means that the ObservableCollection<T>
no longer holds a reference to those items, and if he is the only one which does so, then only in the next GC will those items be collected, where the next GC time is an arbitrary time determined by the runtime.
If you want the items to stop printing those messages, you can do two things:
Item
classUse the disposable pattern to de-register once items no longer need to be of use:
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();
}
}
Upvotes: 2