2010-08-12 3 views
0

У меня возникли проблемы с приложением MVVM WPF. В приложении ViewModel ассоциируется как DataContext для представления с использованием DataTemplate в ResourceDictionary - таким образом, ни один из объектов не имеет ссылки на код в другом. У моего ViewModel есть неуправляемый ресурс, который должен быть выпущен, когда мой ViewModel ушел. (В этом случае мой ресурс является классом с использованием внешней DLL)Закрытие неуправляемых ресурсов при закрытии приложения WPF

Если я фактически не использую DLL, когда я закрываю приложение, вызывается финализатор для моего неуправляемого ресурса, который очищает DLL (Я реализую IDisposable). Там все хорошо.

Если я использую DLL, когда я закрываю приложение, финализатор для моего ресурса не вызывается и процесс не заканчивается. Если я сломаюсь, я вижу, что DLL блокирует вызов на System.Net.Sockets.Socket.Receive(). Я предполагаю, что происходит то, что каким-то образом моя DLL переживает мою ViewModel, поэтому ViewModel никогда не завершается.

Из того, что я читал, это плохой дизайн, чтобы полагаться на завершаемый объект - вы не можете доверять GC. Итак, какие параметры мне нужно вызвать CleanUp() на моем ресурсе, когда я хочу закрыть приложение - если у View и ViewModel нет ссылок друг на друга?

Редактировать: Для некоторого дополнительного чтения это blog post о финализаторах, на которые я ссылался.

Редактировать 2: Я придумал решение, в котором я доволен, поэтому я решил, что добавлю его для потомков и псевдо-закрыть этот вопрос. При запуске приложения я инициализирую основной View и ViewModel для своего приложения, поэтому это единственный источник, который имеет ссылку на оба. Я подключил EventHandler по адресу View.Closed, который запускает метод CleanUp() на моем ViewModel, который способен распространять эту логику во всем приложении. Я поддерживаю MVVM и получаю очистку от оскорбительных ресурсов без особых проблем.

ответ

1

Нет, вы можете определенно доверять GC. Вы не можете доверять DLL, которые вы не пишете, которые запускают потоки, которые вызывают Socket.Receive(). Вам придется заняться этим, поговорив с владельцем DLL-кода. Если вы действительно создали поток самостоятельно, установите для его свойства IsBackground значение true.

+0

Я попытался вызвать вызов DLL в потоке, где я установил IsBackground в true, но у меня все еще была такая же проблема. Я надеялся, что если диспетчеру UI больше нечего делать, он может заставить другого остановиться. – bsg

+0

+1 для установки IsBackground в true (если у вас есть поток). Вы * можете * полагаться на GC для завершения вашего объекта, но вы * не можете * полагаться на GC для бесплатной ссылки на объекты для вас. Если в вашем объекте есть ссылки на любой другой объект, не выделенный (обработчики событий - большой), GC не удалит ваш объект. По сути, у вас все еще может быть утечка памяти с помощью .NET и съесть всю доступную память на вашем компьютере, только те, которые не попадают в ваш AppDomain, поэтому, когда ваше приложение отключается, вы можете * доверять GC, чтобы освободить всю память, связанную с вашим приложение. – Doug

Смежные вопросы