2015-08-13 12 views
10

Powiedzmy mam ObservableCollection zajęć:Wyrejestrowanie z wydarzeń w ObservableCollection

CustomClassName testClass = new CustomClassName(); 
ObservableCollection<CustomClassName> collection = new ObservableCollection<CustomClassName>(); 
testClass.SomeEvent += OnSomeEvent; 
collection.add(testClass); 

Kiedy będę usuwać elementy z kolekcji, muszę ręcznie wypisać się z listy zdarzeń (OnSomeEvent) lub należy pozostawić go na GC? Jaki jest najlepszy sposób na rezygnację z subskrypcji?

Odpowiedz

5

Jeśli spodziewasz się zebrania przedmiotu, to tak, musisz zrezygnować z subskrypcji.

Aby to zrobić, zwykle sposobem jest:

collection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(collection_CollectionChanged); 

// ... 
// and add the method 
void collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
{ 
    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) 
    { 
     foreach (var it in e.OldItems) { 
      var custclass = it as CustomClassName; 
      if (custclass != null) custclass.SomeEvent -= OnSomeEvent; 
     } 
    } 
} 
+0

Thnx. A jaki jest najlepszy sposób? Robię to w collectionChanged. – Sasha

0

Nie trzeba zrezygnować w normalnym przypadku.

Impreza abonent nie może zapobiec wydawcy (testClass) od gromadzone, ale przeciwnie może się zdarzyć. Nic nie widzę przy życiu, z wyjątkiem .

testClass.SomeEvent += this.OnSomeEvent; 

testClass jest utrzymanie this żyje bo this są przechowywane na liście wywołania testClass.SomeEvent „s (tak, że OnSomeEvent nazywa gdy istnieje SomeEvent). this nie będzie utrzymywał przy życiu testClass subskrybując zdarzenia testClass.

W poniższym kodzie obj jest usuwany z kolekcji i jest śmieci zbierane bez wypisywania, można spróbować uruchomić kod, aby zobaczyć wynik:

void Main() 
{ 
    var obj = new BackgroundWorker(); 
    obj.DoWork += OnSomeEvent; 
    var oc = new ObservableCollection<object>{ obj }; 

    WeakReference objRef = new WeakReference(obj); 
    Console.WriteLine(objRef.IsAlive); 

    oc.Remove(obj); 
    obj = null; 
    GC.Collect(); 

    Console.WriteLine(objRef.IsAlive); 
} 

private void OnSomeEvent(object sender, DoWorkEventArgs e) 
{ 
    Console.WriteLine("work"); 
} 

wyjściowa:

prawda
Fałsz

Możesz rzucić okiem na similar question.

+0

co rozumiesz przez zwykły przypadek? – Sasha

+0

Ponieważ operator + = może być "przeciążony", więc wszystko może się zdarzyć. Jeśli po prostu subskrybujesz wydarzenie, powinno być dobrze. –

+0

@Sasha Dodałem kod, możesz spróbować, jeśli to twój przypadek. –

Powiązane problemy