C # все еще привязан к событию после отключения

В настоящее время я отлаживаю большое (очень большое!) Приложение на C #, которое содержит утечки памяти. В основном он использует Winforms для графического интерфейса, хотя несколько элементов управления созданы в WPF и размещены на ElementHost. До сих пор я обнаруживал, что многие утечки памяти были вызваны тем, что события не были отключены (путем вызова - =), и я смог решить эту проблему.

Однако я только что столкнулся с похожей проблемой. Существует класс WorkItem (недолговечный), который в конструкторе регистрирует события другого класса с именем ClientEntityCache (долгоживущий). События никогда не отключались, и я мог видеть в профилировщике .NET, что из-за этих событий экземпляры WorkItem сохранялись, хотя и не должны. Поэтому я решил заставить WorkItem реализовывать IDisposable и в функции Dispose () отсоединял события следующим образом:

public void Dispose()
{
  ClientEntityCache.EntityCacheCleared -= ClientEntityCache_CacheCleared;
  // Same thing for 10 other events
}

EDIT

Вот код, который я использую для подписки:

public WorkItem()
{
  ClientEntityCache.EntityCacheCleared += ClientEntityCache_CacheCleared;
  // Same thing for 10 other events
}

Я также изменил код для отмены регистрации, чтобы не вызовите новый EntityCacheClearedEventHandler.

КОНЕЦ РЕДАКТИРОВАНИЯ

Я вызвал Dispose в нужных местах кода, который использует WorkItem, и при отладке я вижу, что функция действительно вызывается, и я делаю - = для каждого события. Но я все еще получаю утечку памяти, и мои WorkItems все еще остаются живыми после удаления, а в профилировщике .NET я вижу, что экземпляры остаются в живых, потому что обработчики событий (например, EntityCacheClearedEventHandler) все еще имеют их в своем списке вызовов. Я пытался отцепить их более одного раза (несколько - =), чтобы убедиться, что они не были подключены более одного раза, но это не помогает.

Кто-нибудь знает, почему это происходит или что я могу сделать, чтобы решить эту проблему? Но я все еще получаю утечку памяти, и мои WorkItems все еще остаются живыми после удаления, а в профилировщике .NET я вижу, что экземпляры остаются в живых, потому что обработчики событий (например, EntityCacheClearedEventHandler) все еще имеют их в своем списке вызовов. Я пытался отцепить их более одного раза (несколько - =), чтобы убедиться, что они не были подключены более одного раза, но это не помогает.

Кто-нибудь знает, почему это происходит или что я могу сделать, чтобы решить эту проблему? Но я все еще получаю утечку памяти, и мои WorkItems все еще остаются живыми после удаления, а в профилировщике .NET я вижу, что экземпляры остаются в живых, потому что обработчики событий (например, EntityCacheClearedEventHandler) все еще имеют их в своем списке вызовов. Я пытался отцепить их более одного раза (несколько - =), чтобы убедиться, что они не были подключены более одного раза, но это не помогает.

Кто-нибудь знает, почему это происходит или что я могу сделать, чтобы решить эту проблему? Я полагаю, я мог бы изменить обработчики событий, чтобы использовать слабые делегаты, но это потребовало бы много возиться с большой кучей устаревшего кода.

Спасибо!

РЕДАКТИРОВАТЬ:

Если это поможет, вот корневой путь описанный профилировщиком .NET: многое указывает на ClientEntityCache, который указывает на EntityCacheClearedEventHandler, который указывает на Object [], который указывает на другой экземпляр EntityCacheClearedEventHandler (я не понимаю почему), который указывает на WorkItem.

7
задан Carl 26 May 2011 в 16:30
поделиться