В настоящее время я отлаживаю большое (очень большое!) Приложение на 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.